-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathport_parser.sv
453 lines (325 loc) · 15.8 KB
/
port_parser.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
`timescale 1ns / 1ps
`default_nettype none
//Port field constants
`define SPORT_OFFSET 34
`define SPORT_SIZE 16
`define SPORT_LANES (`SPORT_SIZE/16)
`define DPORT_OFFSET 36
`define DPORT_SIZE 16
`define DPORT_LANES (`DPORT_SIZE/16)
`define CHECK_OFFSET 40
`define CHECK_SIZE 16
`define CHECK_LANES (`CHECK_SIZE/16)
`define LAST_BYTE 41
//The Port Parser
module port_parser
#(
//AXI Stream Params
parameter AXIS_BUS_WIDTH = 64,
parameter AXIS_ID_WIDTH = 4,
parameter AXIS_DEST_WIDTH = 4,
//Derived params for AXI Stream
localparam NUM_BUS_BYTES = AXIS_BUS_WIDTH/8,
localparam NUM_BUS_LANES = AXIS_BUS_WIDTH/16,
localparam NUM_BUS_BYTES_LOG2 = $clog2(NUM_BUS_BYTES),
localparam NUM_AXIS_ID = (2 ** AXIS_ID_WIDTH),
localparam EFF_ID_WIDTH = (AXIS_ID_WIDTH < 1) ? 1 : AXIS_ID_WIDTH,
localparam EFF_DEST_WIDTH = (AXIS_DEST_WIDTH < 1) ? 1 : AXIS_DEST_WIDTH,
//Network Packet Params
parameter MAX_PACKET_LENGTH = 1522,
//Constants and Derived params for network packet
localparam PACKET_LENGTH_CBITS = $clog2(MAX_PACKET_LENGTH+1),
localparam MAX_ADDED_OFFSET = 64,
localparam MAX_OFFSET_INTERNAL = MAX_ADDED_OFFSET + `LAST_BYTE,
localparam MAX_OFFSET_CBITS = $clog2(MAX_OFFSET_INTERNAL+1),
localparam MAX_ADDED_OFFSET_CBITS = $clog2(MAX_ADDED_OFFSET+1),
//Features to implement
parameter bit INCLUDE_SRC_PORT_ACL = 1,
parameter bit INCLUDE_DEST_PORT_ACL = 1,
parameter bit INCLUDE_DEST_PORT_CAM = 1
)
(
//Input AXI stream
input wire [AXIS_BUS_WIDTH-1:0] axis_in_tdata,
input wire [EFF_ID_WIDTH-1:0] axis_in_tid,
input wire [EFF_DEST_WIDTH-1:0] axis_in_tdest,
input wire [NUM_BUS_BYTES-1:0] axis_in_tkeep,
input wire axis_in_tlast,
input wire axis_in_tvalid,
output wire axis_in_tready,
//Output AXI stream
output wire [AXIS_BUS_WIDTH-1:0] axis_out_tdata,
output wire [EFF_ID_WIDTH-1:0] axis_out_tid,
output wire [EFF_DEST_WIDTH-1:0] axis_out_tdest,
output wire [NUM_BUS_BYTES-1:0] axis_out_tkeep,
output wire axis_out_tlast,
output wire axis_out_tvalid,
input wire axis_out_tready,
//Side channel signals from previous stage (ip4 parser)
input wire [NUM_AXIS_ID-1:0] route_mask_in,
input wire poisoned_in,
input wire parsing_done_in,
input wire next_is_config_in,
input wire [PACKET_LENGTH_CBITS-1:0] cur_pos_in,
input wire [MAX_ADDED_OFFSET_CBITS-1:0] added_offset_in,
input wire next_has_ports,
input wire next_can_have_vsid_in,
input wire next_can_have_udp_check,
//Side channel signals passed to next stage (vsid parser/filtering)
output wire [NUM_AXIS_ID-1:0] route_mask_out,
output wire poisoned_out,
output wire parsing_done_out,
output wire next_is_config_out,
output wire has_udp_checksum,
output wire [PACKET_LENGTH_CBITS-1:0] cur_pos_out,
output wire [MAX_ADDED_OFFSET_CBITS-1:0] added_offset_out,
output wire next_can_have_vsid_out,
//Configuration register inputs
output wire [EFF_ID_WIDTH-1:0] port_sel_id,
output wire [EFF_DEST_WIDTH-1:0] port_sel_dest,
input wire [`SPORT_SIZE-1:0] src_port,
input wire match_src_port,
input wire [`DPORT_SIZE-1:0] dest_port,
input wire match_dest_port,
//CAM contents
input wire [`SPORT_SIZE-1:0] ports [NUM_AXIS_ID-1:0],
input wire port_cam_must_match [NUM_AXIS_ID-1:0],
//Clocking
input wire aclk,
input wire aresetn
);
//--------------------------------------------------------//
// Signals Used Throughout //
//--------------------------------------------------------//
//Stream passthrough
assign axis_out_tdata = axis_in_tdata;
assign axis_out_tid = axis_in_tid;
assign axis_out_tdest = axis_in_tdest;
assign axis_out_tkeep = axis_in_tkeep;
assign axis_out_tlast = axis_in_tlast;
assign axis_out_tvalid = axis_in_tvalid;
assign axis_in_tready = axis_out_tready;
//Other passthrough
assign next_is_config_out = next_is_config_in;
assign cur_pos_out = cur_pos_in;
assign added_offset_out = added_offset_in;
assign next_can_have_vsid_out = next_can_have_vsid_in;
//Output select signals for configurations registers
assign port_sel_id = axis_in_tid;
assign port_sel_dest = axis_in_tdest;
//Valid and Ready beat
wire axis_valid_beat = axis_in_tvalid & axis_out_tready;
wire axis_last_beat = axis_valid_beat & axis_in_tlast;
//Current Position Count
wire [PACKET_LENGTH_CBITS-1:0] current_position = cur_pos_in;
//Divide the data bus into 2-byte wide lanes
wire [15:0] axis_in_tdata_lanes [NUM_BUS_LANES-1:0];
generate
for(genvar j = 0; j < NUM_BUS_LANES; j = j + 1) begin : bus_lanes
assign axis_in_tdata_lanes[j] = axis_in_tdata[(j*16)+:16];
end
endgenerate
//Params to split offset counters into important parts
localparam LOWER_PORTION = NUM_BUS_BYTES_LOG2;
localparam UPPER_PORTION = PACKET_LENGTH_CBITS; /*(MAX_OFFSET_CBITS <= NUM_BUS_BYTES_LOG2)
? NUM_BUS_BYTES_LOG2 + 1
: MAX_OFFSET_CBITS;*/
//--------------------------------------------------------//
// Dest Port Parsing //
//--------------------------------------------------------//
//Dest Port lanes
wire [15:0] dest_port_lanes [`DPORT_LANES-1:0];
wire dest_port_lane_valid [`DPORT_LANES-1:0];
//Extract Dest port lanes
generate if (INCLUDE_DEST_PORT_ACL || INCLUDE_DEST_PORT_CAM) begin : inc_parse_dest
for(genvar j = 0; j < `DPORT_LANES; j = j + 1) begin : dest_lanes
//Address where the byte-pair lane is expected
wire [UPPER_PORTION-1:0] lane_offset = `DPORT_OFFSET + (j*2) + added_offset_in;
wire [LOWER_PORTION-1:0] lane_lower = lane_offset[LOWER_PORTION-1:0];
wire [UPPER_PORTION-LOWER_PORTION-1:0] lane_upper = lane_offset[UPPER_PORTION-1:LOWER_PORTION];
//The specific byte-pair lane in the current stream flit
wire [15:0] lane_data = axis_in_tdata_lanes[lane_lower[LOWER_PORTION-1:1]];
wire lane_present = (lane_upper == current_position[PACKET_LENGTH_CBITS-1:LOWER_PORTION]) && axis_valid_beat;
//Assign parsed values
assign dest_port_lanes[j] = lane_data;
assign dest_port_lane_valid[j] = lane_present;
end
end else begin
for(genvar j = 0; j < `DPORT_LANES; j = j + 1) begin : dest_lanes2
assign dest_port_lanes[j] = '0;
assign dest_port_lane_valid[j] = 0;
end
end
endgenerate
//--------------------------------------------------------//
// Source Port Parsing //
//--------------------------------------------------------//
//Source Port lanes
wire [15:0] src_port_lanes [`SPORT_LANES-1:0];
wire src_port_lane_valid [`SPORT_LANES-1:0];
//Extract Dest Port lanes
generate if (INCLUDE_SRC_PORT_ACL) begin : inc_parse_src
for(genvar j = 0; j < `SPORT_LANES; j = j + 1) begin : src_lanes
//Address where the byte-pair lane is expected
wire [UPPER_PORTION-1:0] lane_offset = `SPORT_OFFSET + (j*2) + added_offset_in;
wire [LOWER_PORTION-1:0] lane_lower = lane_offset[LOWER_PORTION-1:0];
wire [UPPER_PORTION-LOWER_PORTION-1:0] lane_upper = lane_offset[UPPER_PORTION-1:LOWER_PORTION];
//The specific byte-pair lane in the current stream flit
wire [15:0] lane_data = axis_in_tdata_lanes[lane_lower[LOWER_PORTION-1:1]];
wire lane_present = (lane_upper == current_position[PACKET_LENGTH_CBITS-1:LOWER_PORTION]) && axis_valid_beat;
//Assign parsed values
assign src_port_lanes[j] = lane_data;
assign src_port_lane_valid[j] = lane_present;
end
end else begin
for(genvar j = 0; j < `SPORT_LANES; j = j + 1) begin : src_lanes2
assign src_port_lanes[j] = '0;
assign src_port_lane_valid[j] = 0;
end
end
endgenerate
//--------------------------------------------------------//
// Checksum Parsing and Detection //
//--------------------------------------------------------//
//Address where the byte-pair lane is expected
wire [UPPER_PORTION-1:0] check_lane_offset = `CHECK_OFFSET;
wire [LOWER_PORTION-1:0] check_lane_lower = check_lane_offset[LOWER_PORTION-1:0];
wire [UPPER_PORTION-LOWER_PORTION-1:0] check_lane_upper = check_lane_offset[UPPER_PORTION-1:LOWER_PORTION];
//The specific byte-pair lane in the current stream flit
wire [15:0] check_lane = axis_in_tdata_lanes[check_lane_lower[LOWER_PORTION-1:1]];
wire check_lane_valid = (check_lane_upper == current_position[PACKET_LENGTH_CBITS-1:LOWER_PORTION]) && axis_valid_beat;
//Signal final result of whether checksum is present
wire out_check_present;
wire cur_check_present;
reg reg_check_present;
//Assign current beat's value
assign cur_check_present = (check_lane != 0);
//Assign Registered values
always @(posedge aclk) begin
if(~aresetn || axis_last_beat) reg_check_present <= 0;
else if(check_lane_valid) reg_check_present <= cur_check_present;
end
//Assign output vlue
assign out_check_present = (check_lane_valid ? cur_check_present : reg_check_present);
//Assign final value
assign has_udp_checksum = (next_can_have_udp_check ? out_check_present : 1'b0);
//--------------------------------------------------------//
// Source Port ACL //
//--------------------------------------------------------//
//Signal final result of src addr ACL
wire out_src_poisoned;
//Include conditionally
generate if(INCLUDE_SRC_PORT_ACL) begin : inc_src_acl
//Signals for acl
reg reg_src_poisoned;
wire [`SPORT_LANES-1:0] cur_src_poisoned;
wire [`SPORT_LANES-1:0] eff_src_poisoned;
//Loop over lanes
for(genvar j = 0; j < `SPORT_LANES; j = j + 1) begin : src_acl
//Assign current beat's value
wire src_port_violation = (src_port_lanes[j] != src_port[(j*16)+:16]) && match_src_port;
assign cur_src_poisoned[j] = src_port_violation;
//Assign final value for this lane
assign eff_src_poisoned[j] = src_port_lane_valid[j] && cur_src_poisoned[j];
end
//Assign Registered values
always @(posedge aclk) begin
if(~aresetn || axis_last_beat) reg_src_poisoned <= 0;
else if(|eff_src_poisoned) reg_src_poisoned <= 1;
end
//Assign final value
assign out_src_poisoned = (|eff_src_poisoned) | reg_src_poisoned;
end else begin
assign out_src_poisoned = 0;
end
endgenerate
//--------------------------------------------------------//
// Dest Port ACL //
//--------------------------------------------------------//
//Signal final result of src addr ACL
wire out_dest_poisoned;
//Include conditionally
generate if(INCLUDE_DEST_PORT_ACL) begin : inc_dest_acl
//Signals for acl
reg reg_dest_poisoned;
wire [`DPORT_LANES-1:0] cur_dest_poisoned;
wire [`DPORT_LANES-1:0] eff_dest_poisoned;
//Loop over lanes
for(genvar j = 0; j < `DPORT_LANES; j = j + 1) begin : dest_acl
//Assign current beat's value
wire dest_port_violation = (dest_port_lanes[j] != dest_port[(j*16)+:16]) && match_dest_port;
assign cur_dest_poisoned[j] = dest_port_violation;
//Assign final value for this lane
assign eff_dest_poisoned[j] = dest_port_lane_valid[j] && cur_dest_poisoned[j];
end
//Assign Registered values
always @(posedge aclk) begin
if(~aresetn || axis_last_beat) reg_dest_poisoned <= 0;
else if (|eff_dest_poisoned) reg_dest_poisoned <= 1;
end
//Assign final value
assign out_dest_poisoned = (|eff_dest_poisoned) | reg_dest_poisoned;
end else begin
assign out_dest_poisoned = 0;
end
endgenerate
//Aggregate of all ACL signals
assign poisoned_out =
(next_has_ports ?
out_src_poisoned | out_dest_poisoned | poisoned_in
:
poisoned_in
);
//--------------------------------------------------------//
// Dest Address Routing CAM //
//--------------------------------------------------------//
//Signal final result of CAM
wire [NUM_AXIS_ID-1:0] out_route_mask;
//Include conditionally
generate if(INCLUDE_DEST_PORT_CAM) begin : inc_cam
//Loop over CAM array
for(genvar k = 0; k < NUM_AXIS_ID; k = k + 1) begin : cam_array
//cam signals
reg reg_out_route_mask;
wire [`DPORT_LANES-1:0] cur_out_route_mask;
wire [`DPORT_LANES-1:0] eff_out_route_mask;
//Loop over lanes
for(genvar j = 0; j < `DPORT_LANES; j = j + 1) begin : dest_cam
//Check current entry match
wire dest_port_match = (dest_port_lanes[j] == ports[k][(j*16)+:16]);
assign cur_out_route_mask[j] = dest_port_match;
assign eff_out_route_mask[j] = !dest_port_lane_valid[j] || cur_out_route_mask[j];
end
//Assign Registered values
always @(posedge aclk) begin
if(~aresetn || axis_last_beat) reg_out_route_mask <= 1;
else if(!(&eff_out_route_mask)) reg_out_route_mask <= 0;
end
//Assign output values
assign out_route_mask[k] = (&eff_out_route_mask) & reg_out_route_mask;
end
end else begin
assign out_route_mask = '1;
end
endgenerate
//Assign Final output
wire [NUM_AXIS_ID-1:0] port_cam_must_match_packed = {>>{port_cam_must_match}};
wire [NUM_AXIS_ID-1:0] internal_route_mask =
~(port_cam_must_match_packed) |
(next_has_ports ? out_route_mask : '0);
assign route_mask_out = internal_route_mask & route_mask_in;
//--------------------------------------------------------//
// End of Processing Indication //
//--------------------------------------------------------//
//Register
reg reg_parsing_done;
//Assign Registered values
always @(posedge aclk) begin
if(~aresetn || axis_last_beat) reg_parsing_done <= 0;
else if (dest_port_lane_valid[`DPORT_LANES-1]) reg_parsing_done <= 1;
end
//Assign output value
wire out_parsing_done = (dest_port_lane_valid[`DPORT_LANES-1] ? 1 : reg_parsing_done);
assign parsing_done_out = (next_has_ports ? out_parsing_done : parsing_done_in);
endmodule
`default_nettype wire