Skip to content

Commit b09dd8a

Browse files
committed
NICA: pktgen AFU
Based on fed4f91
1 parent b1ddb39 commit b09dd8a

22 files changed

+387
-120
lines changed

Diff for: Jenkinsfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ properties ([parameters([
3232
description: 'The version of Vivado HLS to use for the build',
3333
choices: ['2016.2', '2016.4', '2017.2'].join('\n')),
3434
string(name: 'MEMCACHED_CACHE_SIZE', defaultValue: '4096', description: 'Memcached cache size in entries'),
35-
string(name: 'MEMCACHED_KEY_SIZE', defaultValue: '10', description: 'Memcached key size in bytes'),
36-
string(name: 'MEMCACHED_VALUE_SIZE', defaultValue: '10', description: 'Memcached value size in bytes'),
35+
string(name: 'MEMCACHED_KEY_SIZE', defaultValue: '16', description: 'Memcached key size in bytes'),
36+
string(name: 'MEMCACHED_VALUE_SIZE', defaultValue: '16', description: 'Memcached value size in bytes'),
3737
string(name: 'NUM_TC', defaultValue: '4', description: 'Number of traffic classes'),
3838
])])
3939

Diff for: ikernels/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ add_ikernel(memcached "hls/memcached.cpp;hls/passthrough.cpp" "hls/tests/memcach
5050
"memcached-requests.pcap;memcached-responses.pcap;memcached-all-responses.pcap;memcached-requests-16.pcap;memcached-responses-16.pcap;memcached-all-responses-16.pcap")
5151
set(MEMCACHED_CACHE_SIZE "4096" CACHE STRING
5252
"Cache size in entries for the memcached ikernel")
53-
set(MEMCACHED_KEY_SIZE "10" CACHE STRING
53+
set(MEMCACHED_KEY_SIZE "16" CACHE STRING
5454
"Key size in bytes for the memcached ikernel")
55-
set(MEMCACHED_VALUE_SIZE "10" CACHE STRING
55+
set(MEMCACHED_VALUE_SIZE "16" CACHE STRING
5656
"Value size in bytes for the memcached ikernel")
5757
foreach(memcached_target memcached_tests memcached-emu)
5858
target_compile_definitions(${memcached_target} PUBLIC -DMEMCACHED_CACHE_SIZE=${MEMCACHED_CACHE_SIZE}

Diff for: ikernels/hls/echo-impl.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class echo : public hls_ik::ikernel, public hls_ik::virt_gateway_impl<echo> {
5252
/* Metadata of the current packet */
5353
hls_ik::metadata metadata;
5454

55-
bool dummy;
55+
bool dummy, dummy_cache;
56+
hls::stream<bool> dummy_update;
5657

5758
/* By default, respond to all packets. When true, respond to sockperf
5859
* packets with "pong" requests. */

Diff for: ikernels/hls/echo.cpp

+24-9
Original file line numberDiff line numberDiff line change
@@ -94,25 +94,35 @@ void echo::step(hls_ik::ports& p) {
9494
echo_pipeline(p);
9595

9696
ikernel::update();
97+
9798
// TODO: passthrough or drop the host traffic; merge with action stream
9899
// from the echo_pipeline.
99-
if (dummy) {
100-
consume(p.host.metadata_input);
101-
consume(p.host.data_input);
102-
produce(p.net.metadata_output);
103-
produce(p.net.data_output);
100+
dummy_produce_consume: {
101+
dummy_update.read_nb(dummy);
102+
consume(p.host.metadata_input, dummy);
103+
consume(p.host.data_input, dummy);
104+
produce(p.net.metadata_output, dummy);
105+
produce(p.net.data_output, dummy);
104106
}
105107
}
106108

107109
int echo::reg_write(int address, int value, ikernel_id_t ikernel_id)
108110
{
109111
#pragma HLS inline
110-
if (address == ECHO_RESPOND_TO_SOCKPERF) {
112+
switch (address) {
113+
case ECHO_RESPOND_TO_SOCKPERF:
111114
if (respond_to_sockperf_update.full())
112115
return GW_BUSY;
113116
respond_to_sockperf_cache = value;
114117
respond_to_sockperf_update.write(value);
115118
return 0;
119+
case ECHO_DUMMY:
120+
if (dummy_update.full())
121+
return GW_BUSY;
122+
123+
dummy_cache = value;
124+
dummy_update.write_nb(value);
125+
return GW_DONE;
116126
}
117127

118128
return GW_FAIL;
@@ -122,12 +132,17 @@ int echo::reg_write(int address, int value, ikernel_id_t ikernel_id)
122132
int echo::reg_read(int address, int* value, ikernel_id_t ikernel_id)
123133
{
124134
#pragma HLS inline
125-
if (address == ECHO_RESPOND_TO_SOCKPERF) {
135+
switch (address) {
136+
case ECHO_RESPOND_TO_SOCKPERF:
126137
*value = respond_to_sockperf_cache;
127138
return 0;
139+
case ECHO_DUMMY:
140+
*value = dummy_cache;
141+
return GW_DONE;
142+
default:
143+
*value = -1;
144+
return GW_FAIL;
128145
}
129-
130-
return GW_FAIL;
131146
}
132147

133148

Diff for: ikernels/hls/echo.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@
3232
#define LOG_NUM_ECHO_CONTEXTS 6
3333

3434
#define ECHO_RESPOND_TO_SOCKPERF 0
35+
#define ECHO_DUMMY 1
3536

3637
#endif // ECHO_HPP

Diff for: ikernels/hls/memcached-ik.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ class memcached : public hls_ik::ikernel, public hls_ik::virt_gateway_impl<memca
205205
private:
206206
memcached_response generate_response(const memcached_parsed_request &parsed_request, const memcached_value<MEMCACHED_VALUE_SIZE> &value);
207207
void parse_packet(hls_ik::trace_event events[IKERNEL_NUM_EVENTS]);
208-
void action_resolution(hls_ik::pipeline_ports& in, hls_ik::credit_update_registers& host_credit_regs);
208+
void action_resolution(hls_ik::pipeline_ports& in);
209209
void reply_cached_value(hls_ik::pipeline_ports &out);
210210
void intercept_out(hls_ik::pipeline_ports &out);
211211
void handle_parsed_packet(memory& m,

Diff for: ikernels/hls/memcached.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ void memcached::drop_or_pass(hls_ik::pipeline_ports& in) {
206206

207207
}
208208

209-
void memcached::action_resolution(hls_ik::pipeline_ports& in, hls_ik::credit_update_registers& host_credit_regs) {
209+
void memcached::action_resolution(hls_ik::pipeline_ports& in) {
210210
#pragma HLS pipeline enable_flush ii=4
211211
_action_stream.empty_progress();
212212
update_stats();
@@ -539,7 +539,7 @@ void memcached::step(hls_ik::ports& p)
539539
_raw_dup.dup2(p.net.data_input, _parser_data, _buffer_data);
540540
_metadata_dup.dup2(p.net.metadata_input, _parser_metadata, _buffer_metadata);
541541
drop_or_pass(p.net);
542-
action_resolution(p.net, p.host_credit_regs);
542+
action_resolution(p.net);
543543
handle_parsed_packet(p.mem, p.events, p.host);
544544
parse_packet(p.events);
545545
reply_cached_value(p.host);

Diff for: ikernels/hls/passthrough-impl.hpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,16 @@
3939
DECLARE_TOP_FUNCTION(passthrough_top);
4040

4141
struct passthrough_context {
42-
passthrough_context() : ring_id(0) {}
42+
passthrough_context() : ring_id(0), ignore_credits(false) {}
4343

4444
hls_ik::ring_id_t ring_id;
45+
bool ignore_credits;
4546
};
4647

4748
class passthrough_contexts : public context_manager<passthrough_context, LOG_NUM_PASSTHROUGH_CONTEXTS>
4849
{
4950
public:
5051
int rpc(int address, int *value, hls_ik::ikernel_id_t ikernel_id, bool read);
51-
52-
hls_ik::ring_id_t find_ring(const hls_ik::ikernel_id_t& ikernel_id);
5352
};
5453

5554
class passthrough : public hls_ik::ikernel, public hls_ik::virt_gateway_impl<passthrough>
@@ -63,10 +62,9 @@ class passthrough : public hls_ik::ikernel, public hls_ik::virt_gateway_impl<pas
6362

6463
hls::stream<bool> _decisions;
6564
bool _action;
66-
void intercept_in(hls_ik::pipeline_ports& p, hls_ik::credit_update_registers& host_credit_regs);
65+
void intercept_in(hls_ik::pipeline_ports& p);
6766
void drop_or_pass(hls_ik::pipeline_ports& p);
6867
passthrough_contexts contexts;
69-
7068
};
7169

7270
#endif // PASSTHROUGH_IMPL_HPP

Diff for: ikernels/hls/passthrough.cpp

+9-12
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ namespace hls_ik {
4444
}
4545
}
4646

47-
void passthrough::intercept_in(pipeline_ports& p, credit_update_registers& host_credit_regs) {
47+
void passthrough::intercept_in(pipeline_ports& p) {
4848
#pragma HLS pipeline enable_flush ii=3
4949
if (contexts.update())
5050
return;
@@ -53,15 +53,15 @@ void passthrough::intercept_in(pipeline_ports& p, credit_update_registers& host_
5353

5454
if (!p.metadata_input.empty() && !_decisions.full()) {
5555
metadata m = p.metadata_input.read();
56-
ring_id_t ring_id = contexts.find_ring(m.ikernel_id);
56+
passthrough_context& c = contexts[m.ikernel_id];
5757
bool backpressure = false;
5858
// CR Mode
59-
if (ring_id != 0) {
60-
backpressure = !can_transmit(p, m.ikernel_id, ring_id, m.length, HOST);
59+
if (c.ring_id != 0) {
60+
backpressure = !c.ignore_credits && !can_transmit(p, m.ikernel_id, c.ring_id, m.length, HOST);
6161

6262
if (!backpressure) {
63-
new_message(ring_id, HOST);
64-
m.ring_id = ring_id;
63+
new_message(c.ring_id, HOST);
64+
m.ring_id = c.ring_id;
6565
custom_ring_metadata cr;
6666
cr.end_of_message = 1;
6767
m.var = cr;
@@ -111,7 +111,7 @@ void passthrough::drop_or_pass(pipeline_ports& p) {
111111
void passthrough::step(ports& p) {
112112
#pragma HLS inline
113113
pass_packets(p.host);
114-
intercept_in(p.net, p.host_credit_regs);
114+
intercept_in(p.net);
115115
drop_or_pass(p.net);
116116
}
117117

@@ -136,11 +136,6 @@ int passthrough::reg_read(int address, int* value, ikernel_id_t ikernel_id)
136136
return contexts.rpc(address, value, ikernel_id, true);
137137
}
138138

139-
ring_id_t passthrough_contexts::find_ring(const ikernel_id_t& id)
140-
{
141-
return (*this)[id].ring_id;
142-
}
143-
144139
int passthrough_contexts::rpc(int address, int *v, ikernel_id_t ikernel_id, bool read)
145140
{
146141
#pragma HLS inline
@@ -149,6 +144,8 @@ int passthrough_contexts::rpc(int address, int *v, ikernel_id_t ikernel_id, bool
149144
switch (address) {
150145
case PASSTHROUGH_RING_ID:
151146
return gateway_access_field<ring_id_t, &passthrough_context::ring_id>(index, v, read);
147+
case PASSTHROUGH_IGNORE_CREDITS:
148+
return gateway_access_field<bool, &passthrough_context::ignore_credits>(index, v, read);
152149
default:
153150
if (read)
154151
*v = -1;

Diff for: ikernels/hls/passthrough.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@
3030
#define PASSTHROUGH_UUID { 0x38,0xa8,0xea,0x3c,0xcf,0x7d,0x4b,0xfb,0xab,0xe0,0xeb,0xe3,0x55,0xcc,0x94,0x8d }
3131

3232
#define PASSTHROUGH_RING_ID 0x10
33+
#define PASSTHROUGH_IGNORE_CREDITS 0x11
3334

3435
#endif // PASSTHROUGH_HPP

Diff for: ikernels/hls/threshold-impl.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class threshold : public hls_ik::ikernel, public hls_ik::virt_gateway_impl<thres
6969
protected:
7070
threshold_contexts contexts;
7171

72-
void net_ingress(hls_ik::pipeline_ports& p, hls_ik::credit_update_registers& host_credit_regs);
72+
void net_ingress(hls_ik::pipeline_ports& p);
7373
void parser();
7474
void egress(hls_ik::pipeline_ports& p);
7575

Diff for: ikernels/hls/threshold.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ int threshold_contexts::rpc(int address, int *v, ikernel_id_t ikernel_id, bool r
8484
return GW_DONE;
8585
}
8686

87-
void threshold::net_ingress(hls_ik::pipeline_ports& p, credit_update_registers& host_credit_regs)
87+
void threshold::net_ingress(hls_ik::pipeline_ports& p)
8888
{
8989
#pragma HLS pipeline enable_flush ii=3
9090
if (contexts.update())
@@ -203,7 +203,7 @@ void threshold::step(hls_ik::ports& p)
203203
pass_packets(p.host);
204204
hls_helpers::dup(p.net.data_input, data_dup_to_parser, data_dup_to_egress);
205205
parser();
206-
net_ingress(p.net, p.host_credit_regs);
206+
net_ingress(p.net);
207207
egress(p.net);
208208
}
209209

Diff for: manager/nica.py

+27-7
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,32 @@ class Arbiter(Gateway):
7070
def __init__(self, nica, base, done_delay=100, cmd_delay=25):
7171
super(Arbiter, self).__init__(nica, base, done_delay, cmd_delay)
7272

73-
def set_quantum(self, tc, quantum, delay=None):
73+
def quantum_address(self, traffic_class):
74+
'''Calculate gateway offset of the quantum of a given TC'''
75+
return self.ARBITER_SCHEDULER + traffic_class * self.ARBITER_SCHEDULER_STRIDE + \
76+
self.SCHEDULER_DRR_QUANTUM
77+
78+
def set_quantum(self, traffic_class, quantum, delay=None):
7479
"""Speed will be quantum / (sum of all quanta)"""
75-
self.write(self.ARBITER_SCHEDULER +
76-
tc * self.ARBITER_SCHEDULER_STRIDE +
77-
self.SCHEDULER_DRR_QUANTUM, quantum, delay=delay)
80+
self.write(self.quantum_address(traffic_class), quantum, delay=delay)
81+
82+
def get_quantum(self, traffic_class, delay=None):
83+
'''Return the current quantum'''
84+
return self.read(self.quantum_address(traffic_class), delay=delay)
85+
86+
class MMU(object):
87+
BASE = 0x9000
88+
89+
def __init__(self, nica):
90+
self.nica = nica
91+
92+
def set_mapping(self, ikernel_id, ddr_address, delay=None):
93+
assert isinstance(ikernel_id, int)
94+
assert isinstance(ddr_address, int)
95+
# Page aligned
96+
assert ddr_address & ((1 << 12) - 1) == 0
7897

79-
def set_log_saturation(self, port, log_saturation, delay=None):
80-
self.write(self.ARBITER_PORT_STRIDE * port + self.ARBITER_BUCKET_LOG_SATURATION, log_saturation, delay=delay)
98+
self.nica.axi_write(self.BASE + 4 * ikernel_id, ddr_address >> 12, delay=delay)
8199

82100
class NICA(ABC):
83101
'''NICA's main control object. This is an abstract class derived by the simulation version and
@@ -90,6 +108,7 @@ def __init__(self):
90108
self.n2h_arbiter = Arbiter(self, 0x58)
91109
self.h2n_arbiter = Arbiter(self, 0x458)
92110
self.custom_ring = CustomRing(self, 0x78)
111+
self.mmu = MMU(self)
93112

94113
@abstractmethod
95114
def axi_read(self, address, delay=None):
@@ -252,7 +271,8 @@ class FlowTable(Gateway):
252271
FT_RESULT_IKERNEL = 0x19
253272
FT_RESULT_IKERNEL_ID = 0x1a
254273

255-
def set_flow_table_mask(self, daddr, dport, saddr, sport, delay=None):
274+
def set_flow_table_mask(self, daddr=False, dport=False, saddr=False,
275+
sport=False, delay=None):
256276
'''Set the header fields that are included as part of the flow match.'''
257277
mask = 0
258278
if saddr:

0 commit comments

Comments
 (0)