diff options
Diffstat (limited to 'src/systemc/tests/systemc/examples/trie/trie.cpp')
-rw-r--r-- | src/systemc/tests/systemc/examples/trie/trie.cpp | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/src/systemc/tests/systemc/examples/trie/trie.cpp b/src/systemc/tests/systemc/examples/trie/trie.cpp new file mode 100644 index 000000000..7714ce657 --- /dev/null +++ b/src/systemc/tests/systemc/examples/trie/trie.cpp @@ -0,0 +1,308 @@ +#include <stdio.h> +#include "systemc.h" + +SC_MODULE(lc) +{ + sc_out<bool> DIN_rdy; + sc_in<bool> DIN_vld; +#define LOAD_ADDR 0 +#define LOAD_DATA 1 +#define LOOKUP 2 // really op(1) == 1 and op(0) - don't care + sc_in<sc_uint<2> > DIN_op; + sc_in<sc_uint<32> > DIN_data_in; + sc_in<bool> DOUT_rdy; + sc_out<bool> DOUT_vld; + sc_out<sc_uint<32> > DOUT_hop; + sc_in<bool> RSTN; + sc_in_clk CLK; + + void thread(); + sc_uint<20> extract(sc_uint<32>, sc_uint<7>, sc_uint<5>); + sc_uint<10> lookup(sc_uint<32>); + + sc_uint<32> M[1024]; + sc_uint<32> addr; // latched addr for loading memory + + SC_CTOR(lc){ + SC_CTHREAD(thread, CLK.pos()); + reset_signal_is(RSTN,false); + } +}; + +// +// this implements the level-compressed trie +// ip routing algorithm that is proposed in: +// +// "Fast Address Lookup for Internet Routers" +// Stefan Nilsson and Gunnar Karlsson +// Proc IFIP 4th International Conference on BroadBand Communication +// pp. 11-22, 1998 +// +// +void +lc::thread() +{ + if( !RSTN){ + DIN_rdy = 1; + DOUT_vld = 0; + wait(1); + } + + for(;;){ + bool tmp_vld; + bool tmp_rdy; + sc_uint<2> op; + sc_uint<32> data_in; + sc_uint<32> hop; + + { + do { + tmp_vld = DIN_vld.read(); + op = DIN_op.read(); + data_in = DIN_data_in.read(); + wait(1); + } while( !tmp_vld); + } + + if( op == 0){ + // latch address + addr = data_in; + wait(1); + } else if(op == 1){ + // load memory + M[addr] = data_in; + wait(1); + } else if( op[1] == 1){ + // do the ip lookup to next hop + hop = lookup(data_in); + { + DIN_rdy = 0; + do { + tmp_rdy = DOUT_rdy.read(); + wait(1); + } while( !tmp_rdy); + DOUT_vld = 1; + DOUT_hop.write(hop); + DIN_rdy = 1; + wait(1); + DOUT_vld = 0; + } + } + } + +} + +sc_uint<20> +lc::extract(sc_uint<32> x, sc_uint<7> p, sc_uint<5> w) +{ + return( (x>>(p-w+1)) & ~(~0<<w) ); +} + +#define BRANCH(T) T.range(31,27) +#define SKIP(T) T.range(26,20) +#define ADDR(T) T.range(19,0) +#define LEN(T) T.range(31,25) +#define NEXT_HOP(T) T.range(24,15) +#define NEXT_PREFIX(T) T.range(14,0) + +sc_uint<10> +lc::lookup(sc_uint<32> ip) +{ + sc_uint<7> pos; + sc_uint<5> branch; + sc_uint<20> addr; + sc_uint<32> t; + sc_uint<32> ip_prefix; + sc_uint<10> next_hop; + sc_uint<32> mask; + + t = M[0]; + pos = SKIP(t); + branch = BRANCH(t); + addr = ADDR(t); + while(branch != 0){ + addr = addr + extract(ip, pos, branch); + t = M[addr]; + pos = pos - (branch + SKIP(t)); + branch = BRANCH(t); + addr = ADDR(t); + } + + + next_hop = 0; + for(;;) { + addr <<= 1; + + ip_prefix = M[addr]; + t = M[addr|1]; + mask = ~0 << (32-LEN(t)); + if( (ip_prefix&mask) == (ip&mask)){ + next_hop = NEXT_HOP(t); + break; + } + addr = NEXT_PREFIX(t); + if( addr == 0) + break; + } + + return(next_hop); +} + + +/* + * hop prefix(bits 31 .. 0) + * 1 0000* + * 2 0001* + * 3 00101* + * 4 010* + * 5 0110* + * 6 0111* + * 7 100* + * 8 101000* + * 9 101001* + * 10 10101* + * 11 10110* + * 12 10111* + * 13 110* + * 14 11101000* + * 15 11101001* + * + * "not in table" produces a hop of 0 + */ + +#define TRIE(LN, SK, AD) \ + ((((LN)&0x1f)<<27) | (((SK)&0x7f)<<20) | ((AD)&0xfffff)) +#define E(LN, NHP, NPX) \ + ((((LN)&0x7f)<<25) | (((NHP)&0x3ff)<<15) | ((((NPX))&0x7fff))) + + +#define M_SIZE 52 +sc_uint<32> M[M_SIZE] = { +/* TRIE */ +/* 00 */ TRIE(3, 31, 1), +/* 01 */ TRIE(1, 0, 9), +/* 02 */ TRIE(0, 2, 2+11), +/* 03 */ TRIE(0, 0, 3+11), +/* 04 */ TRIE(1, 0, 11), +/* 05 */ TRIE(0, 0, 6+11), +/* 06 */ TRIE(2, 0, 13), +/* 07 */ TRIE(0, 0, 12+11), +/* 08 */ TRIE(1, 4, 17), +/* 09 */ TRIE(0, 0, 0+11), +/* 10 */ TRIE(0, 0, 1+11), +/* 11 */ TRIE(0, 0, 4+11), +/* 12 */ TRIE(0, 0, 5+11), +/* 13 */ TRIE(1, 0, 19), +/* 14 */ TRIE(0, 0, 9+11), +/* 15 */ TRIE(0, 0, 10+11), +/* 16 */ TRIE(0, 0, 11+11), +/* 17 */ TRIE(0, 0, 13+11), +/* 18 */ TRIE(0, 0, 14+11), +/* 19 */ TRIE(0, 0, 7+11), +/* 20 */ TRIE(0, 0, 8+11), +/* 21 */ 0, /* pad */ +/* BASE + PREFIX */ +/* 22 */ 0x00000000, E(4, 1, 0), +/* 24 */ 0x10000000, E(4, 2, 0), +/* 26 */ 0x28000000, E(5, 3, 0), +/* 28 */ 0x40000000, E(3, 4, 0), +/* 31 */ 0x60000000, E(4, 5, 0), +/* 32 */ 0x70000000, E(4, 6, 0), +/* 34 */ 0x80000000, E(3, 7, 0), +/* 36 */ 0xa0000000, E(6, 8, 0), +/* 38 */ 0xa4000000, E(6, 9, 0), +/* 40 */ 0xa8000000, E(5, 10, 0), +/* 42 */ 0xb0000000, E(5, 11, 0), +/* 44 */ 0xb8000000, E(5, 12, 0), +/* 46 */ 0xc0000000, E(3, 13, 0), +/* 48 */ 0xe8000000, E(8, 14, 0), +/* 50 */ 0xe9000000, E(8, 15, 0) +}; + + +struct stimuli { + unsigned int ip; + int hop; +} S[] = { + { 0xf0000000, 0 }, + { 0x10000000, 2 }, + { 0x7c000000, 6 }, + { 0x7c001000, 6 }, + { 0x7c000070, 6 }, +}; + +int +sc_main(int argc, char *argv[]) +{ + sc_clock clk; + sc_signal<bool> reset; + sc_signal<bool> in_rdy; + sc_signal<bool> in_vld; + sc_signal<bool> out_vld; + sc_signal<bool> out_rdy; + sc_signal<sc_uint<2> > op; + sc_signal<sc_uint<32> > data; + sc_signal<sc_uint<32> > hop; + int i; + int m_addr; + lc *lcp; + + lcp = new lc("lc0"); + (*lcp)(in_rdy, in_vld, + op, data, + out_rdy, out_vld, + hop, + reset, clk); + + reset = 0; + sc_start(2, SC_NS); + reset = 1; + sc_start(2, SC_NS); + out_rdy = 1; + + /* + * download the RAM containing + * the routing data + */ + for(i = 0, m_addr = 0; i < M_SIZE; i++, m_addr++){ + while(!in_rdy) sc_start(1, SC_NS); + in_vld = 1; + op.write(LOAD_ADDR); + data.write(m_addr); + do { sc_start(1, SC_NS); in_vld = 0; } while(!in_rdy); + sc_start(1, SC_NS); + in_vld = 1; + op.write(LOAD_DATA); + data.write(M[m_addr]); + do { sc_start(1, SC_NS); in_vld = 0; } while(!in_rdy); + sc_start(1, SC_NS); + } + + /* + * apply some ip's and see what + * comes back as next-hops + */ + for(i = 0; i < sizeof S/sizeof(struct stimuli); i++){ + while(!in_rdy) sc_start(1, SC_NS); + in_vld = 1; + op.write(LOOKUP); + data.write(S[i].ip); + do { sc_start(1, SC_NS); in_vld = 0; } while(!out_vld); + unsigned int h = hop.read(); + if( h != S[i].hop){ + cout << S[i].ip << " should be hop " << S[i].hop + << " got hop " << h << endl; + } + } + cout << "program complete" << endl; + return 0; + +} + + + + + + + + |