1 /*****************************************************************************
2 
3   Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4   more contributor license agreements.  See the NOTICE file distributed
5   with this work for additional information regarding copyright ownership.
6   Accellera licenses this file to you under the Apache License, Version 2.0
7   (the "License"); you may not use this file except in compliance with the
8   License.  You may obtain a copy of the License at
9 
10     http://www.apache.org/licenses/LICENSE-2.0
11 
12   Unless required by applicable law or agreed to in writing, software
13   distributed under the License is distributed on an "AS IS" BASIS,
14   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15   implied.  See the License for the specific language governing
16   permissions and limitations under the License.
17 
18  *****************************************************************************/
19 
20 /*****************************************************************************
21 
22   switch.cpp - This is the implementation file for the asynchronous process
23                "switch".
24 
25   Original Author: Rashmi Goswami, Synopsys, Inc.
26 
27  *****************************************************************************/
28 
29 /*****************************************************************************
30 
31   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
32   changes you are making here.
33 
34       Name, Affiliation, Date:
35   Description of Modification:
36 
37  *****************************************************************************/
38 
39 #include "systemc.h"
40 #include "pkt.h"
41 #include "switch.h"
42 #include "fifo.h"
43 #include "switch_reg.h"
44 #define SIM_NUM 500
45 
entry()46 void mcast_pkt_switch :: entry()
47 {
48   wait();
49 
50   // declarations
51   switch_reg R0;
52   switch_reg R1;
53   switch_reg R2;
54   switch_reg R3;
55   switch_reg temp;
56 
57   int sim_count;
58   int pkt_count;
59   int drop_count;
60 
61   fifo q0_in;
62   fifo q1_in;
63   fifo q2_in;
64   fifo q3_in;
65 
66   fifo q0_out;
67   fifo q1_out;
68   fifo q2_out;
69   fifo q3_out;
70 
71   // FILE *result;
72 
73   // initialization
74   pkt_count = 0;
75   drop_count = 0;
76   sim_count  = 0;
77 
78   q0_in.pntr = 0;
79   q1_in.pntr = 0;
80   q2_in.pntr = 0;
81   q3_in.pntr = 0;
82 
83   q0_out.pntr = 0;
84   q1_out.pntr = 0;
85   q2_out.pntr = 0;
86   q3_out.pntr = 0;
87 
88   q0_in.full  = false;
89   q1_in.full  = false;
90   q2_in.full  = false;
91   q3_in.full  = false;
92 
93   q0_in.empty = true;
94   q1_in.empty = true;
95   q2_in.empty = true;
96   q3_in.empty = true;
97 
98   q0_out.full = false;
99   q1_out.full = false;
100   q2_out.full = false;
101   q3_out.full = false;
102 
103   q0_out.empty = true;
104   q1_out.empty = true;
105   q2_out.empty = true;
106   q3_out.empty = true;
107 
108   R0.free = true;
109   R1.free = true;
110   R2.free = true;
111   R3.free = true;
112 
113   // result = fopen("result","w");
114 
115   cout << endl;
116   cout << "-------------------------------------------------------------------------------" << endl;
117   cout << endl << "             4x4 Multicast Helix Packet Switch Simulation" << endl;
118   cout << "-------------------------------------------------------------------------------" << endl;
119   cout << "  This is the simulation of a 4x4 non-blocking multicast helix packet switch.  " << endl;
120   cout << "  The switch uses a self-routing ring of shift registers to transfer cells     " << endl;
121   cout << "  from one port to another in a pipelined fashion, resolving output contention " << endl;
122   cout << "  and handling multicast switch efficiently." << endl << endl;
123 
124   wait();
125   // functionality
126   while( sim_count++ < SIM_NUM )
127     {
128        wait();
129 
130        /////read input packets//////////////////////////////////
131       if (in0.event())
132        {
133 	 pkt_count++;
134 	 if (q0_in.full == true) drop_count++;
135          else q0_in.pkt_in(in0.read());
136        };
137 
138        if (in1.event())
139        {
140 	 pkt_count++;
141 	 if (q1_in.full == true) drop_count++;
142          else q1_in.pkt_in(in1.read());
143        };
144 
145        if (in2.event())
146        {
147 	 pkt_count++;
148 	 if (q2_in.full == true) drop_count++;
149          else q2_in.pkt_in(in2.read());
150        };
151 
152        if (in3.event())
153        {
154 	 pkt_count++;
155 	 if (q3_in.full == true) drop_count++;
156          else q3_in.pkt_in(in3.read());
157        };
158 
159       /////move the packets from fifo to shift register ring/////
160 
161       if((!q0_in.empty) && R0.free)
162 	{
163           R0.val  = q0_in.pkt_out();
164 	  R0.free = false;
165 	}
166 
167       if((!q1_in.empty) && R1.free)
168 	{
169           R1.val  = q1_in.pkt_out();
170 	  R1.free = false;
171 	}
172       if((!q2_in.empty) && R2.free)
173 	{
174           R2.val  = q2_in.pkt_out();
175 	  R2.free = false;
176 	}
177       if((!q3_in.empty) && R3.free)
178 	{
179           R3.val  = q3_in.pkt_out();
180 	  R3.free = false;
181 	}
182 
183       if((bool)switch_cntrl && switch_cntrl.event())
184 	{
185             /////shift the channel registers /////////////////////////
186             temp = R0;
187             R0 = R1;
188 	    R1 = R2;
189 	    R2 = R3;
190 	    R3 = temp;
191 
192 	    /////write the register values to output fifos////////////
193 	    if ((!R0.free) && (R0.val.dest0) && (!q0_out.full))
194 	      {
195 		q0_out.pkt_in(R0.val);
196 		R0.val.dest0 = false;
197 		if (!(R0.val.dest0|R0.val.dest1|R0.val.dest2|R0.val.dest3)) R0.free = true;
198 	      }
199 
200 	    if ((!R1.free) && (R1.val.dest1) && (!q1_out.full))
201 	      {
202 		q1_out.pkt_in(R1.val);
203 		R1.val.dest1 = false;
204 		if (!(R1.val.dest1|R1.val.dest1|R1.val.dest2|R1.val.dest3)) R1.free = true;
205 	      }
206 	    if ((!R2.free) && (R2.val.dest2) && (!q2_out.full))
207 	      {
208 		q2_out.pkt_in(R2.val);
209 		R2.val.dest2 = false;
210 		if (!(R2.val.dest2|R2.val.dest1|R2.val.dest2|R2.val.dest3)) R2.free = true;
211 	      }
212 	    if ((!R3.free) && (R3.val.dest3) && (!q3_out.full))
213 	      {
214 		q3_out.pkt_in(R3.val);
215 		R3.val.dest3 = false;
216 		if (!(R3.val.dest3|R3.val.dest1|R3.val.dest2|R3.val.dest3)) R3.free = true;
217 	      }
218 
219 	    /////write the packets out//////////////////////////////////
220 	    if (!q0_out.empty) out0.write(q0_out.pkt_out());
221 	    if (!q1_out.empty) out1.write(q1_out.pkt_out());
222 	    if (!q2_out.empty) out2.write(q2_out.pkt_out());
223 	    if (!q3_out.empty) out3.write(q3_out.pkt_out());
224 	}
225     }
226 
227   sc_stop();
228 
229   cout << endl << endl << "-------------------------------------------------------------------------------" << endl;
230   cout << "End of switch operation..." << endl;
231   cout << "Total number of packets received: " <<  pkt_count << endl;
232   cout << "Total number of packets dropped: " <<  drop_count << endl;
233   cout << "Percentage packets dropped:  " <<  drop_count*100/pkt_count << endl;
234   cout << "-------------------------------------------------------------------------------" << endl;
235 
236 }
237