112855Sgabeblack@google.com#include <stdio.h>
212855Sgabeblack@google.com#include "systemc.h"
312855Sgabeblack@google.com
412855Sgabeblack@google.comSC_MODULE(lc)
512855Sgabeblack@google.com{
612855Sgabeblack@google.com	sc_out<bool> DIN_rdy;
712855Sgabeblack@google.com	sc_in<bool>  DIN_vld;
812855Sgabeblack@google.com#define LOAD_ADDR   0
912855Sgabeblack@google.com#define LOAD_DATA   1
1012855Sgabeblack@google.com#define LOOKUP 2 // really op(1) == 1 and op(0) - don't care
1112855Sgabeblack@google.com	sc_in<sc_uint<2> >  DIN_op;
1212855Sgabeblack@google.com	sc_in<sc_uint<32> > DIN_data_in;
1312855Sgabeblack@google.com	sc_in<bool>  DOUT_rdy;
1412855Sgabeblack@google.com	sc_out<bool> DOUT_vld;
1512855Sgabeblack@google.com	sc_out<sc_uint<32> > DOUT_hop;
1612855Sgabeblack@google.com	sc_in<bool> RSTN;
1712855Sgabeblack@google.com	sc_in_clk CLK;
1812855Sgabeblack@google.com
1912855Sgabeblack@google.com	void thread();
2012855Sgabeblack@google.com	sc_uint<20> extract(sc_uint<32>, sc_uint<7>, sc_uint<5>);
2112855Sgabeblack@google.com	sc_uint<10> lookup(sc_uint<32>);
2212855Sgabeblack@google.com
2312855Sgabeblack@google.com	sc_uint<32> M[1024];
2412855Sgabeblack@google.com	sc_uint<32>  addr;	// latched addr for loading memory
2512855Sgabeblack@google.com
2612855Sgabeblack@google.com	SC_CTOR(lc){
2712855Sgabeblack@google.com		SC_CTHREAD(thread, CLK.pos());
2812855Sgabeblack@google.com		reset_signal_is(RSTN,false);
2912855Sgabeblack@google.com	}
3012855Sgabeblack@google.com};
3112855Sgabeblack@google.com
3212855Sgabeblack@google.com//
3312855Sgabeblack@google.com// this implements the level-compressed trie
3412855Sgabeblack@google.com// ip routing algorithm that is proposed in:
3512855Sgabeblack@google.com//
3612855Sgabeblack@google.com// "Fast Address Lookup for Internet Routers"
3712855Sgabeblack@google.com// Stefan Nilsson and Gunnar Karlsson
3812855Sgabeblack@google.com// Proc IFIP 4th International Conference on BroadBand Communication
3912855Sgabeblack@google.com// pp. 11-22, 1998
4012855Sgabeblack@google.com//
4112855Sgabeblack@google.com//
4212855Sgabeblack@google.comvoid
4312855Sgabeblack@google.comlc::thread()
4412855Sgabeblack@google.com{
4512855Sgabeblack@google.com	if( !RSTN){
4612855Sgabeblack@google.com		DIN_rdy = 1;
4712855Sgabeblack@google.com		DOUT_vld = 0;
4812855Sgabeblack@google.com		wait(1);
4912855Sgabeblack@google.com	}
5012855Sgabeblack@google.com
5112855Sgabeblack@google.com	for(;;){
5212855Sgabeblack@google.com		bool tmp_vld;
5312855Sgabeblack@google.com		bool tmp_rdy;
5412855Sgabeblack@google.com		sc_uint<2> op;
5512855Sgabeblack@google.com		sc_uint<32> data_in;
5612855Sgabeblack@google.com		sc_uint<32> hop;
5712855Sgabeblack@google.com
5812855Sgabeblack@google.com                {
5912855Sgabeblack@google.com                do {
6012855Sgabeblack@google.com                	tmp_vld = DIN_vld.read();
6112855Sgabeblack@google.com                        op = DIN_op.read();
6212855Sgabeblack@google.com                        data_in = DIN_data_in.read();
6312855Sgabeblack@google.com                        wait(1);
6412855Sgabeblack@google.com                } while( !tmp_vld);
6512855Sgabeblack@google.com                }
6612855Sgabeblack@google.com
6712855Sgabeblack@google.com		if( op == 0){
6812855Sgabeblack@google.com			// latch address
6912855Sgabeblack@google.com			addr = data_in;
7012855Sgabeblack@google.com			wait(1);
7112855Sgabeblack@google.com		} else if(op == 1){
7212855Sgabeblack@google.com			// load memory
7312855Sgabeblack@google.com			M[addr] = data_in;
7412855Sgabeblack@google.com			wait(1);
7512855Sgabeblack@google.com		} else if( op[1] == 1){
7612855Sgabeblack@google.com			// do the ip lookup to next hop
7712855Sgabeblack@google.com			hop = lookup(data_in);
7812855Sgabeblack@google.com			{
7912855Sgabeblack@google.com				DIN_rdy = 0;
8012855Sgabeblack@google.com				do {
8112855Sgabeblack@google.com					tmp_rdy = DOUT_rdy.read();
8212855Sgabeblack@google.com					wait(1);
8312855Sgabeblack@google.com				} while( !tmp_rdy);
8412855Sgabeblack@google.com				DOUT_vld = 1;
8512855Sgabeblack@google.com				DOUT_hop.write(hop);
8612855Sgabeblack@google.com				DIN_rdy = 1;
8712855Sgabeblack@google.com				wait(1);
8812855Sgabeblack@google.com				DOUT_vld = 0;
8912855Sgabeblack@google.com			}
9012855Sgabeblack@google.com		}
9112855Sgabeblack@google.com	}
9212855Sgabeblack@google.com
9312855Sgabeblack@google.com}
9412855Sgabeblack@google.com
9512855Sgabeblack@google.comsc_uint<20>
9612855Sgabeblack@google.comlc::extract(sc_uint<32> x, sc_uint<7> p, sc_uint<5> w)
9712855Sgabeblack@google.com{
9812855Sgabeblack@google.com	return( (x>>(p-w+1)) & ~(~0<<w) );
9912855Sgabeblack@google.com}
10012855Sgabeblack@google.com
10112855Sgabeblack@google.com#define BRANCH(T)	T.range(31,27)
10212855Sgabeblack@google.com#define SKIP(T)		T.range(26,20)
10312855Sgabeblack@google.com#define ADDR(T)		T.range(19,0)
10412855Sgabeblack@google.com#define LEN(T)		T.range(31,25)
10512855Sgabeblack@google.com#define NEXT_HOP(T)	T.range(24,15)
10612855Sgabeblack@google.com#define NEXT_PREFIX(T)	T.range(14,0)
10712855Sgabeblack@google.com
10812855Sgabeblack@google.comsc_uint<10>
10912855Sgabeblack@google.comlc::lookup(sc_uint<32> ip)
11012855Sgabeblack@google.com{
11112855Sgabeblack@google.com	sc_uint<7> pos;
11212855Sgabeblack@google.com	sc_uint<5> branch;
11312855Sgabeblack@google.com	sc_uint<20> addr;
11412855Sgabeblack@google.com	sc_uint<32> t;
11512855Sgabeblack@google.com	sc_uint<32> ip_prefix;
11612855Sgabeblack@google.com	sc_uint<10> next_hop;
11712855Sgabeblack@google.com	sc_uint<32> mask;
11812855Sgabeblack@google.com
11912855Sgabeblack@google.com	t = M[0];
12012855Sgabeblack@google.com	pos = SKIP(t);
12112855Sgabeblack@google.com	branch = BRANCH(t);
12212855Sgabeblack@google.com	addr = ADDR(t);
12312855Sgabeblack@google.com	while(branch != 0){
12412855Sgabeblack@google.com		addr = addr + extract(ip, pos, branch);
12512855Sgabeblack@google.com		t = M[addr];
12612855Sgabeblack@google.com		pos = pos -  (branch + SKIP(t));
12712855Sgabeblack@google.com		branch = BRANCH(t);
12812855Sgabeblack@google.com		addr = ADDR(t);
12912855Sgabeblack@google.com	}
13012855Sgabeblack@google.com
13112855Sgabeblack@google.com
13212855Sgabeblack@google.com	next_hop = 0;
13312855Sgabeblack@google.com	for(;;) {
13412855Sgabeblack@google.com		addr <<= 1;
13512855Sgabeblack@google.com
13612855Sgabeblack@google.com		ip_prefix = M[addr];
13712855Sgabeblack@google.com		t = M[addr|1];
13812855Sgabeblack@google.com		mask = ~0 << (32-LEN(t));
13912855Sgabeblack@google.com		if( (ip_prefix&mask) == (ip&mask)){
14012855Sgabeblack@google.com			next_hop = NEXT_HOP(t);
14112855Sgabeblack@google.com			break;
14212855Sgabeblack@google.com		}
14312855Sgabeblack@google.com		addr = NEXT_PREFIX(t);
14412855Sgabeblack@google.com		if( addr == 0)
14512855Sgabeblack@google.com			break;
14612855Sgabeblack@google.com	}
14712855Sgabeblack@google.com
14812855Sgabeblack@google.com	return(next_hop);
14912855Sgabeblack@google.com}
15012855Sgabeblack@google.com
15112855Sgabeblack@google.com
15212855Sgabeblack@google.com/*
15312855Sgabeblack@google.com * hop	prefix(bits 31 .. 0)
15412855Sgabeblack@google.com *  1   0000*
15512855Sgabeblack@google.com *  2   0001*
15612855Sgabeblack@google.com *  3   00101*
15712855Sgabeblack@google.com *  4   010*
15812855Sgabeblack@google.com *  5   0110*
15912855Sgabeblack@google.com *  6   0111*
16012855Sgabeblack@google.com *  7   100*
16112855Sgabeblack@google.com *  8   101000*
16212855Sgabeblack@google.com *  9   101001*
16312855Sgabeblack@google.com * 10   10101*
16412855Sgabeblack@google.com * 11   10110*
16512855Sgabeblack@google.com * 12   10111*
16612855Sgabeblack@google.com * 13   110*
16712855Sgabeblack@google.com * 14   11101000*
16812855Sgabeblack@google.com * 15   11101001*
16912855Sgabeblack@google.com *
17012855Sgabeblack@google.com * "not in table" produces a hop of 0
17112855Sgabeblack@google.com */
17212855Sgabeblack@google.com
17312855Sgabeblack@google.com#define TRIE(LN, SK, AD) \
17412855Sgabeblack@google.com  ((((LN)&0x1f)<<27) | (((SK)&0x7f)<<20) | ((AD)&0xfffff))
17512855Sgabeblack@google.com#define E(LN, NHP, NPX) \
17612855Sgabeblack@google.com  ((((LN)&0x7f)<<25) | (((NHP)&0x3ff)<<15) | ((((NPX))&0x7fff)))
17712855Sgabeblack@google.com
17812855Sgabeblack@google.com
17912855Sgabeblack@google.com#define M_SIZE 52
18012855Sgabeblack@google.comsc_uint<32> M[M_SIZE] = {
18112855Sgabeblack@google.com/* TRIE */
18212855Sgabeblack@google.com/* 00 */ TRIE(3, 31, 1),
18312855Sgabeblack@google.com/* 01 */ TRIE(1, 0, 9),
18412855Sgabeblack@google.com/* 02 */ TRIE(0, 2, 2+11),
18512855Sgabeblack@google.com/* 03 */ TRIE(0, 0, 3+11),
18612855Sgabeblack@google.com/* 04 */ TRIE(1, 0, 11),
18712855Sgabeblack@google.com/* 05 */ TRIE(0, 0, 6+11),
18812855Sgabeblack@google.com/* 06 */ TRIE(2, 0, 13),
18912855Sgabeblack@google.com/* 07 */ TRIE(0, 0, 12+11),
19012855Sgabeblack@google.com/* 08 */ TRIE(1, 4, 17),
19112855Sgabeblack@google.com/* 09 */ TRIE(0, 0, 0+11),
19212855Sgabeblack@google.com/* 10 */ TRIE(0, 0, 1+11),
19312855Sgabeblack@google.com/* 11 */ TRIE(0, 0, 4+11),
19412855Sgabeblack@google.com/* 12 */ TRIE(0, 0, 5+11),
19512855Sgabeblack@google.com/* 13 */ TRIE(1, 0, 19),
19612855Sgabeblack@google.com/* 14 */ TRIE(0, 0, 9+11),
19712855Sgabeblack@google.com/* 15 */ TRIE(0, 0, 10+11),
19812855Sgabeblack@google.com/* 16 */ TRIE(0, 0, 11+11),
19912855Sgabeblack@google.com/* 17 */ TRIE(0, 0, 13+11),
20012855Sgabeblack@google.com/* 18 */ TRIE(0, 0, 14+11),
20112855Sgabeblack@google.com/* 19 */ TRIE(0, 0, 7+11),
20212855Sgabeblack@google.com/* 20 */ TRIE(0, 0, 8+11),
20312855Sgabeblack@google.com/* 21 */ 0, 			/* pad */
20412855Sgabeblack@google.com/* BASE + PREFIX */
20512855Sgabeblack@google.com/* 22 */ 0x00000000, E(4, 1, 0),
20612855Sgabeblack@google.com/* 24 */ 0x10000000, E(4, 2, 0),
20712855Sgabeblack@google.com/* 26 */ 0x28000000, E(5, 3, 0),
20812855Sgabeblack@google.com/* 28 */ 0x40000000, E(3, 4, 0),
20912855Sgabeblack@google.com/* 31 */ 0x60000000, E(4, 5, 0),
21012855Sgabeblack@google.com/* 32 */ 0x70000000, E(4, 6, 0),
21112855Sgabeblack@google.com/* 34 */ 0x80000000, E(3, 7, 0),
21212855Sgabeblack@google.com/* 36 */ 0xa0000000, E(6, 8, 0),
21312855Sgabeblack@google.com/* 38 */ 0xa4000000, E(6, 9, 0),
21412855Sgabeblack@google.com/* 40 */ 0xa8000000, E(5, 10, 0),
21512855Sgabeblack@google.com/* 42 */ 0xb0000000, E(5, 11, 0),
21612855Sgabeblack@google.com/* 44 */ 0xb8000000, E(5, 12, 0),
21712855Sgabeblack@google.com/* 46 */ 0xc0000000, E(3, 13, 0),
21812855Sgabeblack@google.com/* 48 */ 0xe8000000, E(8, 14, 0),
21912855Sgabeblack@google.com/* 50 */ 0xe9000000, E(8, 15, 0)
22012855Sgabeblack@google.com};
22112855Sgabeblack@google.com
22212855Sgabeblack@google.com
22312855Sgabeblack@google.comstruct stimuli {
22412855Sgabeblack@google.com	unsigned int ip;
22512855Sgabeblack@google.com	int hop;
22612855Sgabeblack@google.com} S[] = {
22712855Sgabeblack@google.com	{ 0xf0000000, 0 },
22812855Sgabeblack@google.com	{ 0x10000000, 2 },
22912855Sgabeblack@google.com	{ 0x7c000000, 6 },
23012855Sgabeblack@google.com	{ 0x7c001000, 6 },
23112855Sgabeblack@google.com	{ 0x7c000070, 6 },
23212855Sgabeblack@google.com};
23312855Sgabeblack@google.com
23412855Sgabeblack@google.comint
23512855Sgabeblack@google.comsc_main(int argc, char *argv[])
23612855Sgabeblack@google.com{
23712855Sgabeblack@google.com	sc_clock clk;
23812855Sgabeblack@google.com	sc_signal<bool> reset;
23912855Sgabeblack@google.com 	sc_signal<bool> in_rdy;
24012855Sgabeblack@google.com        sc_signal<bool> in_vld;
24112855Sgabeblack@google.com        sc_signal<bool> out_vld;
24212855Sgabeblack@google.com        sc_signal<bool> out_rdy;
24312855Sgabeblack@google.com        sc_signal<sc_uint<2> > op;
24412855Sgabeblack@google.com        sc_signal<sc_uint<32> > data;
24512855Sgabeblack@google.com        sc_signal<sc_uint<32> > hop;
24612855Sgabeblack@google.com	int i;
24712855Sgabeblack@google.com	int m_addr;
24812855Sgabeblack@google.com	lc *lcp;
24912855Sgabeblack@google.com
25012855Sgabeblack@google.com	lcp = new lc("lc0");
25112855Sgabeblack@google.com	(*lcp)(in_rdy, in_vld,
25212855Sgabeblack@google.com	      op, data,
25312855Sgabeblack@google.com	      out_rdy, out_vld,
25412855Sgabeblack@google.com	      hop,
25512855Sgabeblack@google.com	      reset, clk);
25612855Sgabeblack@google.com
25712855Sgabeblack@google.com	reset = 0;
25812855Sgabeblack@google.com	sc_start(2, SC_NS);
25912855Sgabeblack@google.com	reset = 1;
26012855Sgabeblack@google.com	sc_start(2, SC_NS);
26112855Sgabeblack@google.com	out_rdy = 1;
26212855Sgabeblack@google.com
26312855Sgabeblack@google.com	/*
26412855Sgabeblack@google.com	 * download the RAM containing
26512855Sgabeblack@google.com	 * the routing data
26612855Sgabeblack@google.com	 */
26712855Sgabeblack@google.com	for(i = 0, m_addr = 0; i < M_SIZE; i++, m_addr++){
26812855Sgabeblack@google.com		while(!in_rdy) sc_start(1, SC_NS);
26912855Sgabeblack@google.com		in_vld = 1;
27012855Sgabeblack@google.com		op.write(LOAD_ADDR);
27112855Sgabeblack@google.com		data.write(m_addr);
27212855Sgabeblack@google.com		do { sc_start(1, SC_NS); in_vld = 0; } while(!in_rdy);
27312855Sgabeblack@google.com		sc_start(1, SC_NS);
27412855Sgabeblack@google.com		in_vld = 1;
27512855Sgabeblack@google.com		op.write(LOAD_DATA);
27612855Sgabeblack@google.com		data.write(M[m_addr]);
27712855Sgabeblack@google.com		do { sc_start(1, SC_NS); in_vld = 0; } while(!in_rdy);
27812855Sgabeblack@google.com		sc_start(1, SC_NS);
27912855Sgabeblack@google.com	}
28012855Sgabeblack@google.com
28112855Sgabeblack@google.com	/*
28212855Sgabeblack@google.com	 * apply some ip's and see what
28312855Sgabeblack@google.com 	 * comes back as next-hops
28412855Sgabeblack@google.com	 */
28512855Sgabeblack@google.com	for(i = 0; i < sizeof S/sizeof(struct stimuli); i++){
28612855Sgabeblack@google.com		while(!in_rdy) sc_start(1, SC_NS);
28712855Sgabeblack@google.com		in_vld = 1;
28812855Sgabeblack@google.com		op.write(LOOKUP);
28912855Sgabeblack@google.com		data.write(S[i].ip);
29012855Sgabeblack@google.com		do { sc_start(1, SC_NS); in_vld = 0; } while(!out_vld);
29112855Sgabeblack@google.com		unsigned int h = hop.read();
29212855Sgabeblack@google.com		if( h != S[i].hop){
29312855Sgabeblack@google.com			cout << S[i].ip << " should be hop " << S[i].hop
29412855Sgabeblack@google.com                             << " got hop " << h << endl;
29512855Sgabeblack@google.com		}
29612855Sgabeblack@google.com	}
29712855Sgabeblack@google.com	cout << "program complete" << endl;
29812855Sgabeblack@google.com        return 0;
29912855Sgabeblack@google.com
30012855Sgabeblack@google.com}
30112855Sgabeblack@google.com
30212855Sgabeblack@google.com
30312855Sgabeblack@google.com
30412855Sgabeblack@google.com
30512855Sgabeblack@google.com
30612855Sgabeblack@google.com
30712855Sgabeblack@google.com
30812855Sgabeblack@google.com
309