├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── build.sh
├── evaluation
├── hls-legacy
│ ├── CMakeLists.txt
│ ├── cache.hpp
│ ├── firewall.cpp
│ ├── firewall.hpp
│ ├── firewall.tcl
│ ├── main.cpp
│ ├── ntl-legacy
│ │ ├── axi_data.hpp
│ │ ├── dup.hpp
│ │ ├── hash.hpp
│ │ ├── link.hpp
│ │ ├── macros.hpp
│ │ └── maybe.hpp
│ └── parser.hpp
├── p4
│ ├── CMakeLists.txt
│ ├── firewall.p4
│ └── headers.p4
├── scheduler
│ ├── CMakeLists.txt
│ ├── schedulers.cpp
│ └── schedulers.tcl
├── scripts
│ ├── cloc.sh
│ └── prepare-mellanox-shell.sh
├── verilog
│ ├── bit_swap.v
│ ├── byte_swap.v
│ └── exp_hls.v
└── xci
│ ├── .gitignore
│ ├── XilinxSwitch_0
│ └── XilinxSwitch_0.xci
│ ├── axis_data_fifo_0
│ └── axis_data_fifo_0.xci
│ └── fifo_1x64
│ └── fifo_1x64.xci
├── examples
├── common.tcl
└── udp-firewall
│ ├── CMakeLists.txt
│ ├── firewall.cpp
│ ├── firewall.hpp
│ ├── firewall.tcl
│ ├── main.cpp
│ └── parser.hpp
├── ntl
├── axi_data.hpp
├── cache.hpp
├── constant.hpp
├── constexpr.hpp
├── consume.hpp
├── context_manager.hpp
├── counter.hpp
├── dup.hpp
├── enumerate.hpp
├── fold.hpp
├── gateway.hpp
├── last.hpp
├── link.hpp
├── macros.hpp
├── map.hpp
├── maybe.hpp
├── memory.hpp
├── pack.hpp
├── peek_stream.hpp
├── produce.hpp
├── programmable_fifo.hpp
├── push_header.hpp
├── push_suffix.hpp
├── scheduler.hpp
├── stream.hpp
├── tests
│ └── memory_model.hpp
└── zip.hpp
└── tests
├── CMakeLists.txt
├── counter_tests.cpp
├── hash_table_tests.cpp
├── pfifo_tests.cpp
├── push_suffix_tests.cpp
└── stream_tests.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | .*.swp
2 | vivado_hls.log
3 | vivado.log
4 | vivado.jou
5 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.2)
2 |
3 | find_path(XILINX_VIVADO
4 | "vivado"
5 | PATHS /opt/Xilinx/Vivado/2018.2/bin
6 | DOC "Xilinx Vivado path")
7 |
8 | find_path(XILINX_SDNET
9 | "sdnet"
10 | PATHS /opt/Xilinx/SDNet/2018.2/bin
11 | DOC "Xilinx SDNet path")
12 |
13 | set(GTEST_ROOT "$ENV{GTEST_ROOT}" CACHE PATH "Root directory of gtest installation")
14 | find_package(GTest REQUIRED)
15 |
16 | set(THREADS_PREFER_PTHREAD_FLAG ON)
17 | find_package(Threads REQUIRED)
18 |
19 | set (CMAKE_CXX_STANDARD 11)
20 |
21 | include_directories(${XILINX_VIVADO}/../include ${GTEST_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR})
22 | link_libraries(${GTEST_LIBRARIES} pcap Threads::Threads)
23 |
24 | option(BUILD_EVALUATION "Build the evaluation subdirectory contents" OFF)
25 |
26 | set(VIVADO_HLS "env GTEST_ROOT=${GTEST_ROOT} ${XILINX_VIVADO}/vivado_hls")
27 | function(add_hls_target target_name tcl deps)
28 | add_custom_target(${target_name}
29 | COMMAND env GTEST_ROOT=${GTEST_ROOT} ${XILINX_VIVADO}/vivado_hls ${CMAKE_CURRENT_SOURCE_DIR}/${tcl}
30 | DEPENDS ${tcl} ${CMAKE_SOURCE_DIR}/examples/common.tcl ${deps})
31 | endfunction()
32 |
33 | add_custom_target(hls)
34 | add_custom_target(p4)
35 |
36 | add_subdirectory(examples/udp-firewall/)
37 | add_dependencies(hls firewall-hls)
38 | if(BUILD_EVALUATION)
39 | add_subdirectory(evaluation/scheduler/)
40 | add_dependencies(hls schedulers-hls)
41 | add_subdirectory(evaluation/hls-legacy/)
42 | add_dependencies(hls firewall-legacy-hls)
43 | add_subdirectory(evaluation/p4)
44 | add_dependencies(p4 firewall-p4)
45 | endif()
46 |
47 | enable_testing()
48 | # add a check target to build all tests and run them
49 | # see https://cmake.org/Wiki/CMakeEmulateMakeCheck
50 | add_custom_target(check COMMAND env PATH=${TCPDUMP_PATH}:$$PATH ${CMAKE_CTEST_COMMAND})
51 |
52 | function(add_gtest name)
53 | cmake_parse_arguments(GTEST
54 | ""
55 | ""
56 | "SOURCES"
57 | ${ARGN}
58 | )
59 |
60 | add_executable(${name} EXCLUDE_FROM_ALL ${GTEST_SOURCES})
61 | add_dependencies(check ${name})
62 | add_test(${name} ${name})
63 | #target_compile_features(${name} PRIVATE cxx_lambdas)
64 | target_link_libraries(${name} ${GTEST_LIBRARIES}) # ${UUID_LIBRARIES} Threads::Threads)
65 | endfunction(add_gtest)
66 |
67 | add_subdirectory(tests)
68 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 2-Clause License
2 |
3 | Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ntl — Networking Template Library
2 | ===
3 |
4 | ntl is a C++ template library for generating efficient FPGA networking
5 | applications with Xilinx Vivado HLS. This is a research prototype; use at your
6 | own risk. It is free to use as a whole or in parts. Please cite our FCCM'19
7 | paper ["Design Patterns for Code Reuse in HLS Packet Processing Pipelines"](https://haggaie.github.io/files/ntl-fccm19.pdf).
8 |
9 |
10 | BibTeX
11 |
12 | @INPROCEEDINGS{8735559,
13 | author={H. {Eran} and L. {Zeno} and Z. {István} and M. {Silberstein}},
14 | booktitle={2019 IEEE 27th Annual International Symposium on Field-Programmable
15 | Custom Computing Machines (FCCM)},
16 | title={Design Patterns for Code Reuse in {HLS} Packet Processing Pipelines},
17 | year={2019},
18 | volume={},
19 | number={},
20 | pages={208-217},
21 | keywords={field programmable gate arrays;high level synthesis;logic
22 | design;software libraries;class library;FPGA-based SmartNICs;code reuse;HLS
23 | packet processing pipelines;high-level synthesis;high-speed networking
24 | applications;UDP stateless firewall;key-value store cache;FPGA
25 | circuits;Optimization;Tools;C++ languages;Logic gates;Hardware;Field
26 | programmable gate arrays;Data structures;High level synthesis;Design
27 | methodology;Networking;Packet processing},
28 | doi={10.1109/FCCM.2019.00036},
29 | ISSN={2576-2613},
30 | month={April},}
31 |
32 |
33 |
34 | Directory structure
35 | ---
36 |
37 | * [`ntl/`](ntl/) contains the class library itself.
38 | * [`examples/udp-firewall/`](examples/udp-firewall/) contains an example UDP firewall application.
39 | * [`evaluation/`](evaluation/) contains extra code and scripts for evaluating the UDP
40 | firewall example on a Mellanox Innova Flex SmartNIC and comparing against
41 | alternative implementations:
42 |
43 | * [`hls-legacy/`](evaluation/hls-legacy/) and
44 | [`p4/`](evaluation/p4/) implement the same application
45 | without ntl, and using P4/SDNet respectively, in order to compare with the
46 | ntl example.
47 | * [`scripts/`](evaluation/scripts/), [`verilog/`](evaluation/verilog/),
48 | and [`xci/`](evaluation/xci/) provide necessary code to build a bitstream for the
49 | Innova.
50 |
51 | Dependencies
52 | ---
53 |
54 | ntl has been tested with Xilinx Vivado HLS, and Xilinx Vivado 2018.2, and the
55 | evaluation P4 application has been tested with Xilinx SDNet 2018.2.
56 |
57 | ntl relies on [Boost](https://www.boost.org/) libraries, and was tested with version 1.54.0.
58 |
59 | The C simulation test of the UDP firewall example requires
60 | [googletest](https://github.com/google/googletest) and
61 | [libpcap](https://www.tcpdump.org/).
62 |
63 | Building a bitstream for the Innova card requires downloading the SDK from
64 | Mellanox. We have used version 2768 of the SDK.
65 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Copyright (c) 2019 Haggai Eran
4 | # All rights reserved.
5 | #
6 | # Redistribution and use in source and binary forms, with or without modification,
7 | # are permitted provided that the following conditions are met:
8 | #
9 | # * Redistributions of source code must retain the above copyright notice, this
10 | # list of conditions and the following disclaimer.
11 | # * Redistributions in binary form must reproduce the above copyright notice,
12 | # this list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
19 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | #
26 |
27 | dir=$(dirname $0)
28 |
29 | mkdir -p $dir/build
30 | cd $dir/build
31 | cmake ..
32 | make
33 |
34 | make check
35 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set (CMAKE_CXX_STANDARD 98)
2 | add_executable(firewall-legacy firewall.cpp main.cpp)
3 |
4 | add_hls_target(firewall-legacy-hls firewall.tcl firewall-legacy)
5 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/cache.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "ntl-legacy/hash.hpp"
29 |
30 | #include "firewall.hpp"
31 |
32 | #include
33 | #include
34 |
35 | #include "ntl-legacy/macros.hpp"
36 |
37 | // #undef CACHE_ENABLE_DEBUG_COMMANDS
38 |
39 | typedef hash_tag tag_type;
40 | typedef ap_uint<1> mapped_type;
41 | static const int Size = 1024;
42 | static const int Log_Size = 10;
43 |
44 | typedef ap_uint index_t;
45 |
46 | typedef ntl_legacy::hash hash_table_t;
47 | typedef typename hash_table_t::value_type value_type;
48 |
49 | typedef hls::stream value_stream;
50 | typedef hls::stream tag_stream;
51 | typedef hls::stream > > lookup_result_stream;
52 |
53 | enum gateway_command_enum {
54 | HASH_INSERT,
55 | HASH_ERASE,
56 | HASH_READ,
57 | HASH_WRITE,
58 | };
59 |
60 | typedef ntl_legacy::maybe maybe_value_t;
61 |
62 | struct gateway_command
63 | {
64 | gateway_command_enum cmd;
65 | index_t index;
66 | maybe_value_t value;
67 | };
68 | typedef std::pair gateway_response;
69 |
70 | void hash_table(tag_stream& lookups, lookup_result_stream& results,
71 | hls::stream& gateway_commands,
72 | hls::stream& gateway_responses)
73 | {
74 | static hash_table_t _table;
75 |
76 | #pragma HLS pipeline enable_flush ii=3
77 | /* Gateway access are highest priority as they are more rare and lower
78 | * throughput */
79 | gateway_command cmd;
80 | if (gateway_commands.read_nb(cmd)) {
81 | gateway_response resp;
82 |
83 | switch (cmd.cmd) {
84 | case HASH_ERASE: {
85 | tag_type tag = cmd.value.value().first;
86 | bool result = _table.erase(tag);
87 | resp.second = ntl_legacy::make_maybe(result, cmd.value.value());
88 | break;
89 | }
90 | case HASH_INSERT: {
91 | value_type value = cmd.value.value();
92 | ntl_legacy::maybe result = _table.insert(value.first, value.second);
93 | /* Return zero for failure, 1 + index otherwise */
94 | resp.first = result ? result.value() + 1 : 0;
95 | break;
96 | }
97 | #ifdef CACHE_ENABLE_DEBUG_COMMANDS
98 | case HASH_WRITE: {
99 | const bool valid = cmd.value.valid();
100 | const tag_type tag = std::get<0>(cmd.value.value());
101 | const mapped_type value = std::get<1>(cmd.value.value());
102 | _table.set_entry(cmd.index, valid, tag, value);
103 | break;
104 | }
105 | case HASH_READ: {
106 | bool valid = _table.get_valid(cmd.index);
107 | tag_type tag = _table.get_tag(cmd.index);
108 | mapped_type value = _table.get_value(cmd.index);
109 | std::get<1>(resp) = ntl_legacy::make_maybe(valid, std::make_pair(tag, value));
110 | break;
111 | }
112 | #endif
113 | }
114 | gateway_responses.write(resp);
115 | return;
116 | }
117 |
118 | if (!lookups.empty()) {
119 | tag_type tag = lookups.read();
120 | size_t index;
121 | ntl_legacy::maybe > result = _table.find(tag, index);
122 | ntl_legacy::maybe > returned_results =
123 | ntl_legacy::make_maybe(result.valid(),
124 | std::make_pair(result.valid() ? uint32_t(index + 1) : 0,
125 | result.value()));
126 | results.write(returned_results);
127 | }
128 |
129 | }
130 |
131 | /* Command from the gateway */
132 | int gateway_execute_command(const gateway_command& cmd, gateway_response& resp,
133 | hls::stream& gateway_commands,
134 | hls::stream& gateway_responses)
135 |
136 | {
137 | #pragma HLS inline
138 | static bool gateway_command_sent = false;
139 |
140 | if (!gateway_command_sent) {
141 | if (!gateway_commands.write_nb(cmd))
142 | return 1;
143 |
144 | gateway_command_sent = true;
145 | return 1;
146 | } else {
147 | if (!gateway_responses.read_nb(resp))
148 | return 1;
149 |
150 | gateway_command_sent = false;
151 | return 0;
152 | }
153 | }
154 |
155 | /* Insert a new entry from the gateway. Returns GW_DONE when completed,
156 | * *result == 1 if successful. */
157 | int gateway_add_entry(const value_type& value, int *result,
158 | hls::stream& gateway_commands,
159 | hls::stream& gateway_responses)
160 | {
161 | #pragma HLS inline
162 | gateway_command cmd = {
163 | HASH_INSERT,
164 | 0,
165 | value
166 | };
167 | gateway_response resp;
168 |
169 | int ret = gateway_execute_command(cmd, resp, gateway_commands,
170 | gateway_responses);
171 | if (ret == 0)
172 | *result = resp.first;
173 |
174 | return ret;
175 | }
176 |
177 | /* Remove an entry from the gateway. Returns GW_DONE when completed,
178 | * *result == 1 if successful. */
179 | int gateway_delete_entry(const typename hash_table_t::tag_type& tag, int *result,
180 | hls::stream& gateway_commands,
181 | hls::stream& gateway_responses)
182 | {
183 | #pragma HLS inline
184 | gateway_command cmd = {
185 | HASH_ERASE,
186 | 0,
187 | std::make_pair(tag, mapped_type())
188 | };
189 | gateway_response resp;
190 |
191 | int ret = gateway_execute_command(cmd, resp, gateway_commands,
192 | gateway_responses);
193 | if (ret == 0)
194 | *result = resp.second.valid();
195 |
196 | return ret;
197 | }
198 |
199 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/firewall.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #include "parser.hpp"
27 | #include "firewall.hpp"
28 | #include "cache.hpp"
29 |
30 | int firewall_rpc(int addr, gateway_data& data,
31 | hls::stream& gateway_commands,
32 | hls::stream& gateway_responses)
33 | {
34 | #pragma HLS inline
35 | switch (addr) {
36 | case FIREWALL_ADD:
37 | return gateway_add_entry(std::make_pair(data.tag, data.result),
38 | &data.status, gateway_commands,
39 | gateway_responses);
40 | case FIREWALL_DEL:
41 | return gateway_delete_entry(data.tag, &data.status, gateway_commands,
42 | gateway_responses);
43 | default:
44 | return 1;
45 | }
46 | }
47 |
48 | void gateway(gateway_registers& r,
49 | hls::stream& gateway_commands,
50 | hls::stream& gateway_responses)
51 | {
52 | static bool axilite_gateway_done;
53 | #pragma HLS pipeline enable_flush ii=3
54 | DO_PRAGMA_SYN(HLS data_pack variable=r.cmd)
55 | if (r.cmd.go && !axilite_gateway_done) {
56 | int res = firewall_rpc(r.cmd.addr, r.data, gateway_commands,
57 | gateway_responses);
58 | if (res != 1) {
59 | axilite_gateway_done = true;
60 | r.done = 1;
61 | }
62 | } else if (!r.cmd.go && axilite_gateway_done) {
63 | axilite_gateway_done = false;
64 | r.done = 0;
65 | }
66 | }
67 |
68 | void map_metadata_to_hash_lookup(metadata_stream& in,
69 | hls::stream &out)
70 | {
71 | #pragma HLS pipeline ii=3
72 | if (in.empty() || out.full())
73 | return;
74 |
75 | metadata m;
76 | in.read_nb(m);
77 | out.write_nb(hash_tag(m.ip_source, m.ip_dest, m.udp_source, m.udp_dest));
78 | }
79 |
80 | void merge_hash_results(lookup_result_stream& results,
81 | metadata_stream& metadata_in, bool_stream &classify_out)
82 | {
83 | #pragma HLS pipeline ii=1
84 | if (results.empty() || metadata_in.empty() || classify_out.full())
85 | return;
86 |
87 | ntl_legacy::maybe > > val = results.read();
88 | metadata m = metadata_in.read();
89 |
90 | bool forward = !valid_udp(m) ||
91 | (val.valid() ? val.value().second : ap_uint<1>(0));
92 | classify_out.write(forward);
93 | }
94 |
95 | void firewall_step(axi_data_stream& in, axi_data_stream& data_out, bool_stream& classify_out, gateway_registers& g)
96 | {
97 | #pragma HLS inline
98 | static axi_data_stream dup_to_parse;
99 | static metadata_stream parse_to_dup, dup_metadata_to_hash, dup_metadata_to_invalid;
100 | #pragma HLS stream variable=dup_metadata_to_invalid depth=16
101 |
102 | static hls::stream gateway_commands;
103 | static hls::stream gateway_responses;
104 | static tag_stream lookups;
105 | static lookup_result_stream results;
106 |
107 | gateway(g, gateway_commands, gateway_responses);
108 |
109 | dup(in, dup_to_parse, data_out);
110 | parser(dup_to_parse, parse_to_dup);
111 | dup(parse_to_dup, dup_metadata_to_hash, dup_metadata_to_invalid);
112 |
113 | map_metadata_to_hash_lookup(dup_metadata_to_hash, lookups);
114 |
115 | hash_table(lookups, results, gateway_commands, gateway_responses);
116 |
117 | merge_hash_results(results, dup_metadata_to_invalid, classify_out);
118 | }
119 |
120 | void firewall_top(hls::stream& in,
121 | hls::stream& data_out,
122 | bool_stream& classify_out_stream, gateway_registers& g)
123 | {
124 | #pragma HLS dataflow
125 | #pragma HLS interface ap_ctrl_none port=return
126 | #pragma HLS interface axis port=in
127 | #pragma HLS interface axis port=data_out
128 |
129 | #pragma HLS interface s_axilite port=g.cmd offset=0x100
130 | #pragma HLS interface s_axilite port=g.data offset=0x118
131 | #pragma HLS interface s_axilite port=g.done offset=0xfc
132 |
133 | static axi_data_stream in_fifo, out_fifo;
134 | ntl_legacy::link(in, in_fifo);
135 | #pragma HLS stream variable=out_fifo depth=16
136 | ntl_legacy::link(out_fifo, data_out);
137 | firewall_step(in_fifo, out_fifo, classify_out_stream, g);
138 | }
139 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/firewall.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include
29 |
30 | enum {
31 | FIREWALL_ADD = 1,
32 | FIREWALL_DEL = 2,
33 | };
34 |
35 | struct hash_tag : public boost::equality_comparable {
36 | ap_uint<32> ip_source, ip_dest;
37 | ap_uint<16> udp_source, udp_dest;
38 |
39 | hash_tag(ap_uint<32> ip_source = 0, ap_uint<32> ip_dest = 0,
40 | ap_uint<16> udp_source = 0, ap_uint<16> udp_dest = 0) :
41 | ip_source(ip_source),
42 | ip_dest(ip_dest),
43 | udp_source(udp_source),
44 | udp_dest(udp_dest)
45 | {}
46 |
47 | bool operator ==(const hash_tag& o) const
48 | {
49 | return ip_source == o.ip_source &&
50 | ip_dest == o.ip_dest &&
51 | udp_source == o.udp_source &&
52 | udp_dest == o.udp_dest;
53 | }
54 | };
55 |
56 | inline std::size_t hash_value(hash_tag tag)
57 | {
58 | #pragma HLS pipeline enable_flush ii=2
59 | std::size_t seed = 0;
60 |
61 | boost::hash_combine(seed, tag.ip_source.to_int());
62 | boost::hash_combine(seed, tag.ip_dest.to_int());
63 | boost::hash_combine(seed, tag.udp_source.to_short());
64 | boost::hash_combine(seed, tag.udp_dest.to_short());
65 |
66 | return seed;
67 | }
68 |
69 | struct gateway_data
70 | {
71 | hash_tag tag;
72 | ap_uint<1> result;
73 | int status;
74 | };
75 |
76 | struct gateway_registers {
77 | gateway_registers() : cmd(), data(), done(0) {}
78 |
79 | struct {
80 | ap_uint<31> addr;
81 | ap_uint<1> go; // Bit 31
82 | } cmd;
83 |
84 | gateway_data data;
85 |
86 | ap_uint<1> done;
87 | };
88 |
89 | typedef hls::stream > bool_stream;
90 |
91 | void firewall_top(hls::stream& in,
92 | hls::stream& data_out,
93 | bool_stream& classify_out, gateway_registers& g);
94 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/firewall.tcl:
--------------------------------------------------------------------------------
1 | package require Tcl 8.5
2 | set basename [info script]
3 | set basedir [file join [pwd] {*}[lrange [file split $basename] 0 end-1]]
4 | source "$basedir/../../examples/common.tcl"
5 |
6 | create_project firewall {firewall_top} $basedir {firewall.cpp} {main.cpp}
7 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/main.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #include "parser.hpp"
27 | #include "firewall.hpp"
28 | #include "ntl-legacy/macros.hpp"
29 | #include
30 | #include
31 |
32 | struct packet_handler_context {
33 | hls::stream& stream;
34 | int count;
35 | int range_start;
36 | int range_end;
37 |
38 | explicit packet_handler_context(hls::stream& stream) :
39 | stream(stream), count(0) {}
40 | };
41 |
42 | void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
43 | {
44 | packet_handler_context *context = reinterpret_cast(user);
45 | hls::stream& stream = context->stream;
46 | const int b = 32;
47 |
48 | if (h->caplen != h->len)
49 | return;
50 |
51 | if (context->count < context->range_start || context->count >= context->range_end)
52 | goto end;
53 |
54 | for (unsigned word = 0; word < ALIGN(h->len, b); word += b) {
55 | ntl_legacy::axi_data input(0, 0xffffffff, false);
56 | for (unsigned byte = 0; byte < b && word + byte < h->len; ++byte)
57 | input.data(input.data.width - 1 - 8 * byte, input.data.width - 8 - 8 * byte) = bytes[word + byte];
58 | if ((word + b) >= h->len) {
59 | input.keep = ntl_legacy::axi_data::keep_bytes(h->len - word - b);
60 | input.last = true;
61 | }
62 |
63 | stream.write(input);
64 | }
65 | end:
66 | ++context->count;
67 | }
68 |
69 | int read_pcap(
70 | const std::string& filename, hls::stream& stream,
71 | int range_start, int range_end)
72 | {
73 | char errbuf[PCAP_ERRBUF_SIZE];
74 | pcap_t *file = pcap_open_offline(filename.c_str(), errbuf);
75 |
76 | if (!file) {
77 | fprintf(stderr, "%s\n", errbuf);
78 | return -1;
79 | }
80 |
81 | packet_handler_context context(stream);
82 | context.range_start = range_start; context.range_end = range_end;
83 | int ret = pcap_loop(file, 0, &packet_handler, (u_char *)&context);
84 | if (ret == -1) {
85 | perror("pcap_loop returned error");
86 | return -1;
87 | }
88 |
89 | pcap_close(file);
90 |
91 | return context.count;
92 | }
93 |
94 | int write_pcap(FILE* file, hls::stream& stream, bool_stream& classify_out)
95 | {
96 | int ret;
97 | int count = 0;
98 |
99 | pcap_t *dead = pcap_open_dead(DLT_EN10MB, 65535);
100 | if (!dead) {
101 | perror("pcap_open_dead failed");
102 | return -1;
103 | }
104 |
105 | pcap_dumper_t *output = pcap_dump_fopen(dead, file);
106 | if (!output) {
107 | perror("pcap_dump_open failed");
108 | return -1;
109 | }
110 |
111 | u_char buffer[65535];
112 | pcap_pkthdr h = {};
113 | h.len = 0;
114 |
115 | while (!stream.empty()) {
116 | ntl_legacy::axi_data w = stream.read();
117 |
118 | for (int byte = 0; byte < w.data.width / 8; ++byte)
119 | buffer[h.len + byte] = w.data(w.data.width - 1 - byte * 8,
120 | w.data.width - 8 - byte * 8);
121 | h.len += w.data.width / 8;
122 | if (w.last) {
123 | for (int i = 0; i < w.data.width / 8; ++i)
124 | if (!w.keep(i, i))
125 | --h.len;
126 | else
127 | break;
128 | /* Minimum Ethernet packet length is 64 bytes including the FCS */
129 | h.caplen = h.len;
130 | assert(!classify_out.empty());
131 | if (!classify_out.read()) { // drop
132 | pcap_dump((u_char *)output, &h, buffer);
133 | ++count;
134 | }
135 | h.len = 0;
136 | } else {
137 | EXPECT_EQ(~w.keep, 0);
138 | }
139 | }
140 |
141 | EXPECT_EQ(h.len, 0);
142 | EXPECT_TRUE(stream.empty());
143 |
144 | ret = pcap_dump_flush(output);
145 | if (ret) {
146 | perror("pcap_dump_flush returned error");
147 | return -1;
148 | }
149 |
150 | pcap_close(dead);
151 | fdatasync(fileno(file));
152 |
153 | return count;
154 | }
155 |
156 | int main(int argc, char **argv)
157 | {
158 | if (argc < 2) {
159 | printf("Usage: %s in.pcap out.pcap\n", argv[0]);
160 | return 0;
161 | }
162 |
163 | hls::stream in_fifo("in_fifo"), out_fifo("out_fifo");
164 | bool_stream classify_out("classify_out");
165 | gateway_registers regs;
166 | regs.cmd.addr = FIREWALL_ADD;
167 | regs.cmd.go = 1;
168 | regs.data.tag.ip_source = regs.data.tag.ip_dest = 0x7f000001;
169 | regs.data.tag.udp_source = 0x12;
170 | regs.data.tag.udp_dest = 0x0bad;
171 | regs.data.result = 1;
172 | for (int i = 0; i < 15; ++i)
173 | firewall_top(in_fifo, out_fifo, classify_out, regs);
174 | assert(regs.done);
175 | assert(regs.data.status);
176 |
177 | read_pcap(argv[1], in_fifo, 0, 1000000);
178 |
179 | for (int i = 0; i < 3000; ++i)
180 | firewall_top(in_fifo, out_fifo, classify_out, regs);
181 |
182 | FILE *out = fopen(argv[2], "w");
183 | write_pcap(out, out_fifo, classify_out);
184 | return 0;
185 | }
186 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/ntl-legacy/axi_data.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include
29 | #include
30 |
31 | namespace ntl_legacy {
32 | struct raw_axi_data {
33 | ap_uint<256> data;
34 | ap_uint<32> keep;
35 | ap_uint<1> last;
36 | raw_axi_data(ap_uint<256> data = 0, ap_uint<32> keep = 0, ap_uint<1> last = 0) :
37 | data(data), keep(keep), last(last) {}
38 | };
39 |
40 | struct axi_data : public boost::equality_comparable {
41 | ap_uint<256> data;
42 | ap_uint<32> keep;
43 | ap_uint<1> last;
44 |
45 | axi_data() {}
46 | axi_data(const ap_uint<256>& data, const ap_uint<32>& keep, bool last) :
47 | data(data), keep(keep), last(last) {}
48 | axi_data(const raw_axi_data& o) :
49 | data(o.data), keep(o.keep), last(o.last) {}
50 |
51 | static ap_uint<32> keep_bytes(const ap_uint<6>& valid_bytes)
52 | {
53 | return 0xffffffff ^ ((1 << (32 - valid_bytes)) - 1);
54 | }
55 |
56 | void set_data(const char *d, const ap_uint<6>& valid_bytes)
57 | {
58 | keep = keep_bytes(valid_bytes);
59 | for (int byte = 0; byte < 32; ++byte) {
60 | #pragma HLS unroll
61 | const char data_word = (byte < valid_bytes) ? d[byte] : 0;
62 | data(data.width - 1 - 8 * byte, data.width - 8 - 8 * byte) = data_word;
63 | }
64 | }
65 |
66 | int get_data(char *d) const
67 | {
68 | for (int byte = 0; byte < 32; ++byte) {
69 | #pragma HLS unroll
70 | const uint8_t cur = data(data.width - 1 - 8 * byte, data.width - 8 - 8 * byte);
71 | if (keep[31 - byte])
72 | d[byte] = cur;
73 | else
74 | return byte;
75 | }
76 |
77 | return 32;
78 | }
79 |
80 | bool operator ==(const axi_data& other) const { return data == other.data && keep == other.keep && last == other.last; }
81 |
82 | static const int width = 256 + 32 + 1;
83 |
84 | axi_data(const ap_uint d) :
85 | data(d(288, 33)),
86 | keep(d(32, 1)),
87 | last(d(0, 0))
88 | {}
89 |
90 | operator ap_uint() const
91 | {
92 | #pragma HLS inline
93 | return (data, keep, last);
94 | }
95 |
96 | operator raw_axi_data() const
97 | {
98 | #pragma HLS inline
99 | return raw_axi_data(data, keep, last);
100 | }
101 | };
102 |
103 | static inline std::ostream& operator <<(std::ostream& out, const axi_data& d) {
104 | return out << "axi_data(" << std::hex << d.data << ", keep=" << d.keep << (d.last ? ", last)" : ")");
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/ntl-legacy/dup.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "hls_stream.h"
29 |
30 | template
31 | void dup(hls::stream& in, hls::stream& out1, hls::stream& out2)
32 | {
33 | #pragma HLS pipeline
34 | if (in.empty())
35 | return;
36 |
37 | if (out1.full() || out2.full())
38 | return;
39 |
40 | const T flit = in.read();
41 | out1.write(flit);
42 | out2.write(flit);
43 | }
44 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/ntl-legacy/hash.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "maybe.hpp"
29 |
30 | namespace ntl_legacy {
31 | template
32 | class hash
33 | {
34 | public:
35 | typedef Tag tag_type;
36 | typedef std::pair value_type;
37 | typedef uint64_t index_t;
38 |
39 | hash()
40 | {
41 | #pragma HLS resource core=RAM_2P variable=tags
42 | #pragma HLS resource core=RAM_2P variable=values
43 | #pragma HLS resource core=RAM_2P variable=valid
44 | for (int i = 0; i < Size; ++i) {
45 | valid[i] = false;
46 | tags[i] = Tag();
47 | values[i] = Value();
48 | }
49 | }
50 |
51 | maybe insert(const Tag& key, const Value& value)
52 | {
53 | maybe index = lookup(h(key), key);
54 |
55 | if (!index.valid()) {
56 | return index;
57 | }
58 |
59 | if (valid[index.value()] && !insert_overrides)
60 | return maybe();
61 |
62 | tags[index.value()] = key;
63 | values[index.value()] = value;
64 | valid[index.value()] = true;
65 |
66 | return index;
67 | }
68 |
69 | bool erase(const Tag& k)
70 | {
71 | maybe index = lookup(h(k), k);
72 |
73 | if (!index.valid() || !valid[index.value()] || tags[index.value()] != k) {
74 | return false;
75 | }
76 |
77 | valid[index.value()] = false;
78 |
79 | // fill the hole if needed
80 | index_t hash = index.value();
81 | bool found = false;
82 |
83 | for (int i = 1; i < max_hops; ++i) {
84 | if (found) continue;
85 |
86 | index_t cur = (hash + i) % Size;
87 |
88 | if (!valid[cur]) continue;
89 | if (h(tags[cur]) <= index.value()) {
90 | tags[index.value()] = tags[cur];
91 | values[index.value()] = values[cur];
92 | valid[index.value()] = true;
93 | valid[cur] = false;
94 | found = true;
95 | continue;
96 | }
97 | }
98 |
99 | return true;
100 | }
101 |
102 | maybe find(const Tag& k, index_t& out_index) const
103 | {
104 | #pragma HLS inline
105 | maybe index = lookup(h(k), k);
106 |
107 | if (!index.valid() || !valid[index.value()] || tags[index.value()] != k) {
108 | return maybe();
109 | }
110 |
111 | Value value = values[index.value()];
112 | out_index = index.value();
113 | return maybe(value);
114 | }
115 |
116 | maybe find(const Tag& k) const
117 | {
118 | #pragma HLS inline
119 | index_t index;
120 |
121 | return find(k, index);
122 | }
123 |
124 | /* For debugging */
125 | #ifdef CACHE_ENABLE_DEBUG_COMMANDS
126 | bool set_entry(index_t index, bool set_valid, const Tag& tag, const Value& value) {
127 | bool result = !valid[index];
128 |
129 | valid[index] = set_valid;
130 | tags[index] = tag;
131 | values[index] = value;
132 |
133 | return result;
134 | }
135 |
136 | const Tag& get_tag(index_t index) const { return tags[index % Size]; }
137 | const Value& get_value(index_t index) const { return values[index % Size]; }
138 | bool get_valid(index_t index) const { return valid[index % Size]; }
139 | #endif
140 |
141 | private:
142 | index_t h(const Tag& tag) const { return boost::hash()(tag) % Size; }
143 |
144 | maybe lookup(index_t hash, const Tag& tag) const {
145 | for (int i = 0; i < max_hops; ++i) {
146 | hash = (hash + 1) % Size;
147 | if (!valid[hash] || tags[hash] == tag)
148 | return maybe(hash);
149 | }
150 |
151 | return maybe();
152 | }
153 |
154 | Tag tags[Size];
155 | Value values[Size];
156 | bool valid[Size];
157 | };
158 | }
159 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/ntl-legacy/link.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | namespace ntl_legacy {
29 |
30 | template
31 | void link(InputStream& in, OutputStream& out)
32 | {
33 | #pragma HLS pipeline
34 | if (in.empty() || out.full())
35 | return;
36 |
37 | out.write(in.read());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/ntl-legacy/macros.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #define PRAGMA_SUB(x) _Pragma(#x)
29 | /* Use DO_PRAGMA to be able to have C preprocessor expansion in a pragma */
30 | #define DO_PRAGMA(x) PRAGMA_SUB(x)
31 |
32 | /* RTL/C co-simulation doesn't work well with certain definitions, so make them
33 | * conditional */
34 | #ifdef SIMULATION_BUILD
35 | # define _PragmaSyn(x)
36 | # define DO_PRAGMA_SYN(x)
37 | # define _PragmaSim(x) _Pragma(x)
38 | # define DO_PRAGMA_SIM(x) DO_PRAGMA(x)
39 | #else
40 | # define _PragmaSyn(x) _Pragma(x)
41 | # define DO_PRAGMA_SYN(x) DO_PRAGMA(x)
42 | # define _PragmaSim(x)
43 | # define DO_PRAGMA_SIM(x)
44 | #endif
45 |
46 | #define ALIGN(x,a) __ALIGN_MASK(x,(a)-1)
47 | #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
48 |
49 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/ntl-legacy/maybe.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | namespace ntl_legacy {
29 |
30 | template
31 | class maybe {
32 | public:
33 | maybe(bool valid, const Value& v) : _valid(valid), _value(v) {}
34 | maybe(const Value& v) : _valid(true), _value(v) {}
35 | maybe() : _valid(false) {}
36 |
37 | bool valid() const { return _valid; }
38 | const Value& value() const { return _value; }
39 |
40 | operator bool() const { return valid(); }
41 |
42 | void reset() { _valid = false; }
43 | private:
44 | bool _valid;
45 | Value _value;
46 | };
47 |
48 | template
49 | maybe make_maybe(bool valid, const Value& v)
50 | {
51 | return maybe(valid, v);
52 | }
53 |
54 | template
55 | maybe make_maybe(const Value& v)
56 | {
57 | return maybe(true, v);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/evaluation/hls-legacy/parser.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "ntl-legacy/dup.hpp"
29 | #include "ntl-legacy/link.hpp"
30 | #include "ntl-legacy/axi_data.hpp"
31 |
32 | #include
33 | #include
34 |
35 | typedef hls::stream axi_data_stream;
36 |
37 | struct metadata {
38 | ap_uint<32> ip_source, ip_dest;
39 | ap_uint<16> ether_type, udp_source, udp_dest;
40 | ap_uint<8> ip_protocol;
41 |
42 | metadata() :
43 | ip_source(0), ip_dest(0), ether_type(0), udp_source(0), udp_dest(0),
44 | ip_protocol(0)
45 | {}
46 |
47 | };
48 |
49 | inline bool valid_ip(metadata m)
50 | {
51 | #pragma HLS inline
52 | return m.ether_type == ETHERTYPE_IP;
53 | }
54 |
55 | inline bool valid_udp(metadata m)
56 | {
57 | #pragma HLS inline
58 | return valid_ip(m) && m.ip_protocol == IPPROTO_UDP;
59 | }
60 |
61 | typedef hls::stream metadata_stream;
62 |
63 | template
64 | ap_uint<8 * (end - start)> range(const T& val)
65 | {
66 | // static_assert(end > start, "Invalid range.");
67 |
68 | const int width = T::width;
69 |
70 | return val(width - 8 * start - 1, width - 8 * end);
71 | }
72 |
73 | inline void parser(axi_data_stream& in, metadata_stream& out)
74 | {
75 | #pragma HLS pipeline
76 | static enum { IDLE, FIRST, REST } state = IDLE;
77 | static metadata ret;
78 |
79 | ntl_legacy::axi_data flit;
80 |
81 | switch (state) {
82 | case IDLE:
83 | if (in.empty() || out.full())
84 | return;
85 |
86 | in.read_nb(flit);
87 | ret = metadata();
88 | ret.ether_type = range<12, 14>(flit.data);
89 | ret.ip_protocol = range<23, 24>(flit.data);
90 | ret.ip_source = range<26, 30>(flit.data);
91 | ret.ip_dest(31, 16) = range<30, 32>(flit.data);
92 | state = flit.last ? IDLE : FIRST;
93 | if (flit.last)
94 | out.write_nb(ret);
95 | break;
96 | case FIRST:
97 | if (in.empty() || out.full())
98 | return;
99 |
100 | in.read_nb(flit);
101 | ret.ip_dest(15, 0) = range<0, 2>(flit.data);
102 | ret.udp_source = range<2, 4>(flit.data);
103 | ret.udp_dest = range<4, 6>(flit.data);
104 | out.write_nb(ret);
105 | state = flit.last ? IDLE : REST;
106 | break;
107 | case REST:
108 | if (in.empty())
109 | return;
110 |
111 | in.read_nb(flit);
112 | state = flit.last ? IDLE : REST;
113 | break;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/evaluation/p4/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_custom_command(OUTPUT firewall.sdnet
2 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/firewall.p4
3 | COMMAND ${XILINX_SDNET}/p4c-sdnet -o firewall.sdnet ${CMAKE_CURRENT_SOURCE_DIR}/firewall.p4)
4 | add_custom_command(OUTPUT firewall/XilinxSwitch/XilinxSwitch.v
5 | firewall/XilinxSwitch/XilinxSwitch.TB/XilinxSwitch.cpp
6 | firewall/XilinxSwitch/XilinxSwitch.TB/sdnet_lib.cpp
7 | DEPENDS firewall.sdnet
8 | COMMAND ${XILINX_SDNET}/sdnet -workDir firewall -busWidth 256 -controlClock 216.25 -lineClock 216.25 -lookupClock 216.25 firewall.sdnet)
9 |
10 | add_custom_target(firewall-p4
11 | DEPENDS firewall/XilinxSwitch/XilinxSwitch.v
12 | WORKING_DIRECTORY firewall/XilinxSwitch
13 | COMMAND sed -e 's/xcvu095-ffva2104-2-e/xcku060-ffva1156-2-i/'
14 | -e 's/xcvu9p-flgc2104-2-e/xcku060-ffva1156-2-i/' --in-place XilinxSwitch_vivado_packager.tcl &&
15 | rm -rf XilinxSwitch_vivado &&
16 | ${XILINX_VIVADO}/vivado -mode batch -source XilinxSwitch_vivado_packager.tcl)
17 |
18 |
--------------------------------------------------------------------------------
/evaluation/p4/firewall.p4:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2018 Haggai Eran
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #include "headers.p4"
27 |
28 | control IngressPipeline(inout headers_t hdr, inout metadata_t ctrl) {
29 | action pass() {
30 | ctrl.dropped = 0;
31 | }
32 | action drop() {
33 | ctrl.dropped = 1;
34 | }
35 |
36 | table flows {
37 | key = {
38 | hdr.ipv4.src : exact;
39 | hdr.ipv4.dst : exact;
40 | hdr.udp.sport : exact;
41 | hdr.udp.dport : exact;
42 | }
43 | actions = { pass; drop; }
44 | size = 1024;
45 | default_action = pass;
46 | }
47 |
48 | apply {
49 | if (hdr.ipv4.isValid() && hdr.udp.isValid())
50 | flows.apply();
51 | else
52 | pass();
53 | }
54 | }
55 |
56 | XilinxSwitch(Parser(), IngressPipeline(), Deparser()) main;
57 |
--------------------------------------------------------------------------------
/evaluation/p4/headers.p4:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------------
2 | // This file is owned and controlled by Xilinx and must be used solely //
3 | // for design, simulation, implementation and creation of design files //
4 | // limited to Xilinx devices or technologies. Use with non-Xilinx //
5 | // devices or technologies is expressly prohibited and immediately //
6 | // terminates your license. //
7 | // //
8 | // XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" SOLELY //
9 | // FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY //
10 | // PROVIDING THIS DESIGN, CODE, OR INFORMATION AS ONE POSSIBLE //
11 | // IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, XILINX IS //
12 | // MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE FROM ANY //
13 | // CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING ANY //
14 | // RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY //
15 | // DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE //
16 | // IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR //
17 | // REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF //
18 | // INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A //
19 | // PARTICULAR PURPOSE. //
20 | // //
21 | // Xilinx products are not intended for use in life support appliances, //
22 | // devices, or systems. Use in such applications are expressly //
23 | // prohibited. //
24 | // //
25 | // (c) Copyright 1995-2016 Xilinx, Inc. //
26 | // All rights reserved. //
27 | //----------------------------------------------------------------------------
28 | #include "xilinx.p4"
29 |
30 | typedef bit<48> MacAddress;
31 | typedef bit<32> IPv4Address;
32 |
33 | header ethernet_h {
34 | MacAddress dst;
35 | MacAddress src;
36 | bit<16> type;
37 | }
38 |
39 | header ipv4_h {
40 | bit<4> version;
41 | bit<4> ihl;
42 | bit<8> tos;
43 | bit<16> len;
44 | bit<16> id;
45 | bit<3> flags;
46 | bit<13> frag;
47 | bit<8> ttl;
48 | bit<8> proto;
49 | bit<16> chksum;
50 | IPv4Address src;
51 | IPv4Address dst;
52 | }
53 |
54 | header udp_h {
55 | bit<16> sport;
56 | bit<16> dport;
57 | bit<16> len;
58 | bit<16> chksum;
59 | }
60 |
61 | struct headers_t {
62 | ethernet_h ethernet;
63 | ipv4_h ipv4;
64 | udp_h udp;
65 | }
66 |
67 | struct metadata_t {
68 | bit<1> dropped;
69 | }
70 |
71 | @Xilinx_MaxPacketRegion(1518*8) // in bits
72 | parser Parser(packet_in pkt, out headers_t hdr) {
73 |
74 | state start {
75 | pkt.extract(hdr.ethernet);
76 | transition select(hdr.ethernet.type) {
77 | 0x0800 : parse_ipv4;
78 | default : accept;
79 | }
80 | }
81 |
82 | state parse_ipv4 {
83 | pkt.extract(hdr.ipv4);
84 | transition select(hdr.ipv4.proto) {
85 | 17 : parse_udp;
86 | default : accept;
87 | }
88 | }
89 |
90 | state parse_udp {
91 | pkt.extract(hdr.udp);
92 | transition accept;
93 | }
94 | }
95 |
96 | @Xilinx_MaxPacketRegion(1518*8) // in bits
97 | control Deparser(in headers_t hdr, packet_out pkt) {
98 | apply {
99 | pkt.emit(hdr.ethernet);
100 | pkt.emit(hdr.ipv4);
101 | pkt.emit(hdr.udp);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/evaluation/scheduler/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(schedulers schedulers.cpp)
2 |
3 | add_hls_target(schedulers-hls schedulers.tcl schedulers)
4 |
--------------------------------------------------------------------------------
/evaluation/scheduler/schedulers.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #include "ntl/scheduler.hpp"
27 | #include "ntl/link.hpp"
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | typedef ntl::gateway_registers gateway_registers;
34 |
35 | struct scheduler_cmd {
36 | int port;
37 | uint32_t quantum;
38 | };
39 |
40 | template
41 | class sched_wrapper
42 | {
43 | public:
44 | typedef ntl::scheduler scheduler_t;
45 | typedef typename scheduler_t::index_t index_t;
46 |
47 | static void decode_gateway_address(int address, int& flow_id, int& cmd,
48 | bool read)
49 | {
50 | flow_id = address >> 2;
51 | cmd = address & 1;
52 | read = address & 2;
53 | }
54 |
55 | void step(gateway_registers& g)
56 | {
57 | #pragma HLS pipeline II=3
58 | /* Inline the gateway here */
59 | #pragma HLS inline region
60 | gateway.gateway(g, [&](int addr, int& data) -> bool {
61 | #pragma HLS inline
62 | int flow_id, cmd;
63 | bool read;
64 | decode_gateway_address(addr, flow_id, cmd, read);
65 | return sched.rpc(cmd, &data, flow_id, read);
66 | });
67 |
68 | if (sched.update())
69 | return;
70 |
71 | index_t req;
72 | if (!tx_requests.empty()) {
73 | req = tx_requests.read();
74 | sched.schedule(req);
75 | }
76 |
77 | if (scheduler_decision.full())
78 | return;
79 |
80 | index_t selected_stream;
81 | uint32_t quota;
82 | if (!sched.next_flow(&selected_stream, "a))
83 | return;
84 |
85 | scheduler_decision.write(scheduler_cmd{selected_stream, quota});
86 | }
87 | ntl::stream tx_requests;
88 | ntl::stream scheduler_decision;
89 | private:
90 | scheduler_t sched;
91 | ntl::gateway_impl gateway;
92 | };
93 |
94 | #define NUM_SCHEDULERS 8
95 | void sched_top(BOOST_PP_ENUM_PARAMS(NUM_SCHEDULERS, gateway_registers& g),
96 | BOOST_PP_ENUM_PARAMS(NUM_SCHEDULERS, ntl::stream& tx_requests),
97 | BOOST_PP_ENUM_PARAMS(NUM_SCHEDULERS, ntl::stream& scheduler_decision))
98 | {
99 | #pragma HLS dataflow
100 | #pragma HLS interface ap_ctrl_none port=return
101 |
102 | #define BOOST_PP_LOCAL_MACRO(n) \
103 | GATEWAY_OFFSET(g ## n, 0x100, 0x118, 0xfc) \
104 | static sched_wrapper sched ## n; \
105 | sched ## n.step(g ## n); \
106 | ntl::link(tx_requests ## n, sched ## n.tx_requests); \
107 | ntl::link(sched ## n.scheduler_decision, scheduler_decision ## n);
108 | #define BOOST_PP_LOCAL_LIMITS (0, NUM_SCHEDULERS - 1)
109 | %:include BOOST_PP_LOCAL_ITERATE()
110 | }
111 |
112 | int main()
113 | {
114 | return 0;
115 | }
116 |
--------------------------------------------------------------------------------
/evaluation/scheduler/schedulers.tcl:
--------------------------------------------------------------------------------
1 | package require Tcl 8.5
2 | set basename [info script]
3 | set basedir [file join [pwd] {*}[lrange [file split $basename] 0 end-1]]
4 | source "$basedir/../../examples/common.tcl"
5 |
6 | create_project schedulers {sched_top} $basedir {schedulers.cpp} {}
7 |
--------------------------------------------------------------------------------
/evaluation/scripts/cloc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Copyright (c) 2018-2019 Haggai Eran
4 | # All rights reserved.
5 | #
6 | # Redistribution and use in source and binary forms, with or without modification,
7 | # are permitted provided that the following conditions are met:
8 | #
9 | # * Redistributions of source code must retain the above copyright notice, this
10 | # list of conditions and the following disclaimer.
11 | # * Redistributions in binary form must reproduce the above copyright notice,
12 | # this list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
19 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | #
26 |
27 | dir=$(dirname $0)
28 |
29 | cmd() {
30 | echo "$@"
31 | "$@"
32 | }
33 |
34 | echo P4:
35 | cmd cloc --force-lang=C++,p4 $dir/../p4/*.p4
36 | echo ----
37 |
38 | echo Firewall:
39 | cmd cloc $(find $dir/../../examples/udp-firewall/ -maxdepth 1 -name '*.[hc]pp' -not -name main.cpp)
40 | echo ----
41 |
42 | echo Library:
43 | cmd cloc $dir/../../ntl/
44 | echo ----
45 |
46 | echo Legacy firewall:
47 | cmd cloc $(find $dir/../hls-legacy/ -name '*.[hc]pp' -not -name main.cpp)
48 | echo ----
49 |
--------------------------------------------------------------------------------
/evaluation/scripts/prepare-mellanox-shell.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 | #
3 | # Copyright (c) 2016-2017 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
4 | # All rights reserved.
5 | #
6 | # Redistribution and use in source and binary forms, with or without modification,
7 | # are permitted provided that the following conditions are met:
8 | #
9 | # * Redistributions of source code must retain the above copyright notice, this
10 | # list of conditions and the following disclaimer.
11 | # * Redistributions in binary form must reproduce the above copyright notice,
12 | # this list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
19 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | #
26 |
27 | tarball=$(readlink -f ${1:-newton_ku060_40g_v2768.tar})
28 |
29 | if [ "$#" -lt 1 ] ; then
30 | echo "Missing argument: tarball"
31 | echo "Using: $tarball as a default"
32 | fi
33 |
34 | if [ ! -f "$tarball" ] ; then
35 | echo "File not found: $tarball"
36 | exit 1
37 | fi
38 |
39 | rm -rf user
40 | mkdir -p user
41 | cd user
42 |
43 | dirs=({examples/exp_hls/{vlog,xdc},mlx,project,scripts,tb/exp_vlog})
44 | tar xvf $tarball ${dirs[@]}
45 | cd ..
46 | #patch -p1 -d user < ../scripts/mellanox-shell-scripts.patch
47 |
48 | ln -snf examples/exp_hls user/sources
49 | ln -snf ../../../sysvlog user/sources/
50 | ln -snf ../../../../p4/build/firewall/XilinxSwitch/XilinxSwitch_vivado/XilinxSwitch/XilinxSwitch.srcs/sources_1/imports/ user/sources/ip_repo
51 |
52 | ln -snf ../../../../xci user/examples/exp_hls/xci
53 | cd user/examples/exp_hls/vlog
54 | cp -sf ../../../../../verilog/* .
55 | cp -sf ../../../../../hls/firewall/40Gbps/impl/ip/hdl/verilog/*.v .
56 | cp -sf ../../../../../hls/firewall/40Gbps/impl/ip/hdl/verilog/*.dat .
57 |
58 | cd -
59 |
--------------------------------------------------------------------------------
/evaluation/verilog/bit_swap.v:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2018-2019 Haggai Eran
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | // swap bit order (e.g. for tkeep reversal)
27 |
28 | module bit_swap #(
29 | parameter N = 32
30 | )(
31 | input [N - 1:0] in,
32 | output [N - 1:0] out
33 | );
34 |
35 | genvar i;
36 | generate for (i = 0; i < N; i = i + 1) begin : assign_bit
37 | assign out[i] = in[N - 1 - i];
38 | end endgenerate
39 |
40 | endmodule
41 |
--------------------------------------------------------------------------------
/evaluation/verilog/byte_swap.v:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2018-2019 Haggai Eran
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | // swap bytes for endianess change
27 |
28 | module byte_swap #(
29 | parameter N = 32
30 | )(
31 | input [8 * N - 1:0] in,
32 | output [8 * N - 1:0] out
33 | );
34 |
35 | genvar i;
36 | generate for (i = 0; i < N; i = i + 1) begin : assign_byte
37 | assign out[8 * i + 7:8 * i] = in[8 * (N - i) - 1 : 8 * (N - 1 - i)];
38 | end endgenerate
39 |
40 | endmodule
41 |
--------------------------------------------------------------------------------
/evaluation/xci/.gitignore:
--------------------------------------------------------------------------------
1 | *.xml
2 | *.veo
3 | *.vho
4 | *.xdc
5 | *.v
6 | *.vhdl
7 | *.dcp
8 | hdl
9 | misc
10 | sim
11 | synth
12 | constraints
13 | doc
14 | simulation
15 | summary.log
16 |
--------------------------------------------------------------------------------
/evaluation/xci/axis_data_fifo_0/axis_data_fifo_0.xci:
--------------------------------------------------------------------------------
1 |
2 |
3 | xilinx.com
4 | xci
5 | unknown
6 | 1.0
7 |
8 |
9 | axis_data_fifo_0
10 |
11 |
12 |
13 | 100000000
14 | 1
15 | 1
16 | 1
17 | 0
18 | undef
19 | 0.000
20 | 32
21 | 0
22 | 3
23 | 12
24 | ACTIVE_LOW
25 |
26 |
27 |
28 | 100000000
29 | 0.000
30 | ACTIVE_LOW
31 |
32 | 100000000
33 | 1
34 | 1
35 | 1
36 | 0
37 | undef
38 | 0.000
39 | 32
40 | 0
41 | 3
42 | 12
43 | ACTIVE_LOW
44 |
45 |
46 |
47 | 100000000
48 | 0.000
49 | ACTIVE_LOW
50 | 0
51 | 0b00000000000000000000000010111011
52 | 256
53 | 1
54 | 3
55 | 12
56 | kintexu
57 | 64
58 | 2
59 | 0
60 | 2
61 | 0
62 | axis_data_fifo_0
63 | 64
64 | 2
65 | 1
66 | 1
67 | 1
68 | 0
69 | 0
70 | 2
71 | 32
72 | 0
73 | 3
74 | 12
75 | kintexu
76 |
77 | xcku060
78 | ffva1156
79 | VERILOG
80 |
81 | MIXED
82 | -2
83 | I
84 | TRUE
85 | TRUE
86 | IP_Flow
87 | 18
88 | TRUE
89 | .
90 |
91 | .
92 | 2018.2
93 | OUT_OF_CONTEXT
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 |
--------------------------------------------------------------------------------
/examples/common.tcl:
--------------------------------------------------------------------------------
1 | package require Tcl 8.5
2 |
3 | set common_basename [info script]
4 | set common_basedir [file join [pwd] {*}[lrange [file split $common_basename] 0 end-1]]
5 |
6 | proc create_project {name top dir files tb_files} {
7 | open_project -reset "$name-hls"
8 |
9 | global env common_basedir
10 | set_top $top
11 | set GTEST_ROOT $::env(GTEST_ROOT)
12 | set cflags "-std=gnu++0x -Wno-gnu-designator \
13 | -I$GTEST_ROOT/include -I$common_basedir/.."
14 |
15 | set ldflags "-lpcap -L$GTEST_ROOT -lgtest"
16 |
17 | foreach f $files {
18 | set f [file join $dir $f]
19 | add_files $f -cflags $cflags
20 | }
21 |
22 | foreach f $tb_files {
23 | if {![file exists $f]} {
24 | set f [file join $dir $f]
25 | }
26 | add_files -tb $f -cflags $cflags
27 | }
28 |
29 | open_solution "40Gbps"
30 | set_part {xcku060-ffva1156-2-i}
31 | create_clock -period "216.25MHz"
32 | config_rtl -prefix ${name}_
33 | config_interface -m_axi_addr64
34 | if {[llength $tb_files] > 0} {
35 | csim_design -ldflags $ldflags
36 | }
37 | csynth_design
38 | export_design -format ip_catalog
39 | }
40 |
--------------------------------------------------------------------------------
/examples/udp-firewall/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(firewall firewall.cpp main.cpp)
2 |
3 | add_hls_target(firewall-hls firewall.tcl firewall)
4 |
--------------------------------------------------------------------------------
/examples/udp-firewall/firewall.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #include "ntl/map.hpp"
27 | #include "parser.hpp"
28 | #include "firewall.hpp"
29 |
30 | #include
31 |
32 | #include
33 |
34 | void firewall::step(axi_data_stream& in, axi_data_stream& data_out, bool_stream& classify_out, gateway_registers& g)
35 | {
36 | #pragma HLS inline
37 | #pragma HLS stream variable=invalid_udp depth=16
38 | gateway.gateway(g, [&](int addr, gateway_data& data) -> int { return rpc(addr, data); });
39 |
40 | dup_data.step(in);
41 | parse.step(dup_data._streams[0]);
42 | dup_metadata.step(parse.out);
43 |
44 | ntl::map(dup_metadata._streams[0], hash.lookups, [](const metadata& m) {
45 | return hash_tag{m.ip_source, m.ip_dest, m.udp_source, m.udp_dest};
46 | });
47 |
48 | hash.hash_table();
49 |
50 | ntl::map(dup_metadata._streams[1], invalid_udp, [](const metadata& m) {
51 | return !m.valid_udp();
52 | });
53 |
54 | ntl::map(hash.results, result_with_default, [](const ntl::maybe >& val) {
55 | return val.valid() ? std::get<1>(val.value()) : ap_uint<1>(0);
56 | });
57 |
58 | merge_hash_results.step(std::logical_or >(),
59 | result_with_default, invalid_udp);
60 |
61 | link(merge_hash_results.out, classify_out);
62 | link(dup_data._streams[1], data_out);
63 | }
64 |
65 | int firewall::rpc(int addr, gateway_data& data)
66 | {
67 | switch (addr) {
68 | case FIREWALL_ADD:
69 | return hash.gateway_add_entry(std::make_tuple(data.tag, data.result), &data.status);
70 | case FIREWALL_DEL:
71 | return hash.gateway_delete_entry(data.tag, &data.status);
72 | default:
73 | return ntl::GW_FAIL;
74 | }
75 | }
76 |
77 | void firewall_top(ntl::stream& in,
78 | ntl::stream& data_out,
79 | bool_stream& classify_out, gateway_registers& g)
80 | {
81 | #pragma HLS dataflow
82 | #pragma HLS interface ap_ctrl_none port=return
83 | #pragma HLS interface axis port=in._stream
84 | #pragma HLS interface axis port=data_out._stream
85 |
86 | GATEWAY_OFFSET(g, 0x100, 0x118, 0xfc)
87 | static firewall f;
88 | static axi_data_stream in_fifo, out_fifo;
89 | ntl::link(in, in_fifo);
90 | #pragma HLS stream variable=out_fifo depth=16
91 | ntl::link(out_fifo, data_out);
92 | f.step(in_fifo, out_fifo, classify_out, g);
93 | }
94 |
--------------------------------------------------------------------------------
/examples/udp-firewall/firewall.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "ntl/cache.hpp"
29 |
30 | enum {
31 | FIREWALL_ADD = 1,
32 | FIREWALL_DEL = 2,
33 | };
34 |
35 | struct hash_tag : public boost::equality_comparable {
36 | ap_uint<32> ip_source, ip_dest;
37 | ap_uint<16> udp_source, udp_dest;
38 |
39 | hash_tag(ap_uint<32> ip_source = 0, ap_uint<32> ip_dest = 0,
40 | ap_uint<16> udp_source = 0, ap_uint<16> udp_dest = 0) :
41 | ip_source(ip_source),
42 | ip_dest(ip_dest),
43 | udp_source(udp_source),
44 | udp_dest(udp_dest)
45 | {}
46 |
47 | hash_tag(const hash_tag& o) = default;
48 |
49 | bool operator ==(const hash_tag& o) const
50 | {
51 | return ip_source == o.ip_source &&
52 | ip_dest == o.ip_dest &&
53 | udp_source == o.udp_source &&
54 | udp_dest == o.udp_dest;
55 | }
56 | };
57 |
58 | namespace ntl {
59 | template <>
60 | struct pack {
61 | static const int width = 96;
62 |
63 | static ap_uint to_int(const hash_tag& e) {
64 | return (e.ip_source, e.ip_dest, e.udp_source, e.udp_dest);
65 | }
66 |
67 | static hash_tag from_int(const ap_uint& d) {
68 | return hash_tag{
69 | range<0, 4>(d),
70 | range<4, 8>(d),
71 | range<8, 10>(d),
72 | range<10, 12>(d)};
73 | }
74 | };
75 | }
76 |
77 | inline std::size_t hash_value(hash_tag tag)
78 | {
79 | #pragma HLS pipeline enable_flush ii=2
80 | std::size_t seed = 0;
81 |
82 | boost::hash_combine(seed, tag.ip_source.to_int());
83 | boost::hash_combine(seed, tag.ip_dest.to_int());
84 | boost::hash_combine(seed, tag.udp_source.to_short());
85 | boost::hash_combine(seed, tag.udp_dest.to_short());
86 |
87 | return seed;
88 | }
89 |
90 | struct gateway_data
91 | {
92 | hash_tag tag;
93 | ap_uint<1> result;
94 | int status;
95 | };
96 |
97 | typedef ntl::gateway_registers gateway_registers;
98 |
99 | typedef ntl::stream > bool_stream;
100 | typedef ntl::hash_table_wrapper, 1024> hash_t;
101 |
102 | class firewall
103 | {
104 | public:
105 | void step(axi_data_stream& in, axi_data_stream& data_out, bool_stream& classify_out, gateway_registers& g);
106 | int rpc(int addr, gateway_data& data);
107 |
108 | private:
109 | ntl::gateway_impl gateway;
110 |
111 | ntl::dup dup_data;
112 | ntl::dup dup_metadata;
113 | parser parse;
114 | hash_t hash;
115 | bool_stream invalid_udp;
116 | bool_stream result_with_default;
117 | ntl::zip_with, ap_uint<1>, ap_uint<1> > merge_hash_results;
118 | };
119 |
--------------------------------------------------------------------------------
/examples/udp-firewall/firewall.tcl:
--------------------------------------------------------------------------------
1 | package require Tcl 8.5
2 |
3 | set basename [info script]
4 | set basedir [file join [pwd] {*}[lrange [file split $basename] 0 end-1]]
5 | source "$basedir/../common.tcl"
6 |
7 | create_project firewall {firewall_top} $basedir {firewall.cpp} {main.cpp}
8 |
--------------------------------------------------------------------------------
/examples/udp-firewall/main.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #include "parser.hpp"
27 | #include "firewall.hpp"
28 | #include "ntl/macros.hpp"
29 | #include
30 | #include
31 |
32 | struct packet_handler_context {
33 | axi_data_stream& stream;
34 | int count;
35 | int range_start;
36 | int range_end;
37 |
38 | explicit packet_handler_context(axi_data_stream& stream) :
39 | stream(stream), count(0) {}
40 | };
41 |
42 | void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
43 | {
44 | auto context = reinterpret_cast(user);
45 | axi_data_stream& stream = context->stream;
46 | const int b = 32;
47 |
48 | if (h->caplen != h->len)
49 | return;
50 |
51 | if (context->count < context->range_start || context->count >= context->range_end)
52 | goto end;
53 |
54 | for (unsigned word = 0; word < ALIGN(h->len, b); word += b) {
55 | ntl::axi_data input(0, 0xffffffff, false);
56 | for (unsigned byte = 0; byte < b && word + byte < h->len; ++byte)
57 | input.data(input.data.width - 1 - 8 * byte, input.data.width - 8 - 8 * byte) = bytes[word + byte];
58 | if ((word + b) >= h->len) {
59 | input.keep = ntl::axi_data::keep_bytes(h->len - word - b);
60 | input.last = true;
61 | }
62 |
63 | stream.write(input);
64 | }
65 | end:
66 | ++context->count;
67 | }
68 |
69 | int read_pcap(
70 | const std::string& filename, axi_data_stream& stream,
71 | int range_start, int range_end)
72 | {
73 | char errbuf[PCAP_ERRBUF_SIZE];
74 | pcap_t *file = pcap_open_offline(filename.c_str(), errbuf);
75 |
76 | if (!file) {
77 | fprintf(stderr, "%s\n", errbuf);
78 | return -1;
79 | }
80 |
81 | auto context = packet_handler_context(stream);
82 | context.range_start = range_start; context.range_end = range_end;
83 | int ret = pcap_loop(file, 0, &packet_handler, (u_char *)&context);
84 | if (ret == -1) {
85 | perror("pcap_loop returned error");
86 | return -1;
87 | }
88 |
89 | pcap_close(file);
90 |
91 | return context.count;
92 | }
93 |
94 | int write_pcap(FILE* file, axi_data_stream& stream, bool_stream& classify_out)
95 | {
96 | int ret;
97 | int count = 0;
98 |
99 | pcap_t *dead = pcap_open_dead(DLT_EN10MB, 65535);
100 | if (!dead) {
101 | perror("pcap_open_dead failed");
102 | return -1;
103 | }
104 |
105 | pcap_dumper_t *output = pcap_dump_fopen(dead, file);
106 | if (!output) {
107 | perror("pcap_dump_open failed");
108 | return -1;
109 | }
110 |
111 | u_char buffer[65535];
112 | pcap_pkthdr h = {};
113 | h.len = 0;
114 |
115 | while (!stream.empty()) {
116 | ntl::axi_data w = stream.read();
117 |
118 | for (int byte = 0; byte < w.data.width / 8; ++byte)
119 | buffer[h.len + byte] = w.data(w.data.width - 1 - byte * 8,
120 | w.data.width - 8 - byte * 8);
121 | h.len += w.data.width / 8;
122 | if (w.last) {
123 | for (int i = 0; i < w.data.width / 8; ++i)
124 | if (!w.keep(i, i))
125 | --h.len;
126 | else
127 | break;
128 | /* Minimum Ethernet packet length is 64 bytes including the FCS */
129 | h.caplen = h.len;
130 | assert(!classify_out.empty());
131 | if (!classify_out.read()) { // drop
132 | pcap_dump((u_char *)output, &h, buffer);
133 | ++count;
134 | }
135 | h.len = 0;
136 | } else {
137 | EXPECT_EQ(~w.keep, 0);
138 | }
139 | }
140 |
141 | EXPECT_EQ(h.len, 0);
142 | EXPECT_TRUE(stream.empty());
143 |
144 | ret = pcap_dump_flush(output);
145 | if (ret) {
146 | perror("pcap_dump_flush returned error");
147 | return -1;
148 | }
149 |
150 | pcap_close(dead);
151 | fdatasync(fileno(file));
152 |
153 | return count;
154 | }
155 |
156 | int main(int argc, char **argv)
157 | {
158 | if (argc < 2) {
159 | printf("Usage: %s in.pcap out.pcap\n", argv[0]);
160 | return 0;
161 | }
162 |
163 | firewall f;
164 | axi_data_stream in_fifo("in_fifo"), out_fifo("out_fifo");
165 | bool_stream classify_out("classify_out");
166 | gateway_registers regs = {};
167 | regs.cmd = { FIREWALL_ADD, 1};
168 | regs.data.tag.ip_source = regs.data.tag.ip_dest = 0x7f000001;
169 | regs.data.tag.udp_source = 0x12;
170 | regs.data.tag.udp_dest = 0x0bad;
171 | regs.data.result = 1;
172 | for (int i = 0; i < 15; ++i)
173 | f.step(in_fifo, out_fifo, classify_out, regs);
174 | assert(regs.done);
175 | assert(regs.data.status);
176 |
177 | read_pcap(argv[1], in_fifo, 0, 1000000);
178 |
179 | for (int i = 0; i < 3000; ++i)
180 | f.step(in_fifo, out_fifo, classify_out, regs);
181 |
182 | FILE *out = fopen(argv[2], "w");
183 | write_pcap(out, out_fifo, classify_out);
184 | return 0;
185 | }
186 |
--------------------------------------------------------------------------------
/examples/udp-firewall/parser.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "ntl/stream.hpp"
29 | #include "ntl/dup.hpp"
30 | #include "ntl/zip.hpp"
31 | #include "ntl/fold.hpp"
32 | #include "ntl/link.hpp"
33 | #include "ntl/enumerate.hpp"
34 | #include "ntl/axi_data.hpp"
35 |
36 | #include
37 | #include
38 |
39 | typedef ntl::stream axi_data_stream;
40 |
41 | struct metadata {
42 | ap_uint<32> ip_source, ip_dest;
43 | ap_uint<16> ether_type, udp_source, udp_dest;
44 | ap_uint<8> ip_protocol;
45 |
46 | metadata() :
47 | ip_source(0), ip_dest(0), ether_type(0), udp_source(0), udp_dest(0),
48 | ip_protocol(0)
49 | {}
50 |
51 | bool valid_ip() const
52 | {
53 | return ether_type == ETHERTYPE_IP;
54 | }
55 |
56 | bool valid_udp() const
57 | {
58 | return valid_ip() && ip_protocol == IPPROTO_UDP;
59 | }
60 | };
61 |
62 | typedef ntl::stream metadata_stream;
63 |
64 | typedef std::tuple, ntl::axi_data> numbered_data;
65 |
66 | namespace ntl {
67 | template <>
68 | inline bool last(const numbered_data& flit)
69 | {
70 | return std::get<1>(flit).last;
71 | }
72 | }
73 |
74 | template
75 | ap_uint<8 * (end - start)> range(const T& val)
76 | {
77 | static_assert(end > start, "Invalid range.");
78 |
79 | const int width = T::width;
80 |
81 | return val(width - 8 * start - 1, width - 8 * end);
82 | }
83 |
84 | class extract_metadata : public ntl::fold
85 | {
86 | public:
87 | typedef ntl::fold base;
88 | typedef typename base::in_t in_t;
89 | extract_metadata() : base(metadata())
90 | {}
91 |
92 | void step(in_t& in)
93 | {
94 | #pragma HLS pipeline
95 | base::step(in, [](const metadata& cur, const numbered_data& num_data) -> metadata {
96 | metadata ret = cur;
97 | ntl::axi_data flit;
98 | ap_uint<16> index;
99 |
100 | std::tie(index, flit) = num_data;
101 |
102 | if (index == 0) {
103 | ret.ether_type = range<12, 14>(flit.data);
104 | ret.ip_protocol = range<23, 24>(flit.data);
105 | ret.ip_source = range<26, 30>(flit.data);
106 | ret.ip_dest(31, 16) = range<30, 32>(flit.data);
107 | } else if (index == 1) {
108 | ret.ip_dest(15, 0) = range<0, 2>(flit.data);
109 | ret.udp_source = range<2, 4>(flit.data);
110 | ret.udp_dest = range<4, 6>(flit.data);
111 | }
112 | return ret;
113 | });
114 | }
115 | };
116 |
117 | /*
118 | template
119 | class extract_header
120 | {
121 | public:
122 | extract_header() : _flit_count(0) {}
123 |
124 | static const unsigned len = end - start;
125 | typedef ap_uint<8 * len> field_t;
126 | typedef ntl::stream field_stream;
127 | field_stream out;
128 |
129 | void step(axi_data_stream& in)
130 | {
131 | static_assert(31 / 32 == (30 / 32), "No support for fields that span multiple flits at the moment.");
132 | static_assert((end - 1) / 32 == (start / 32), "No support for fields that span multiple flits at the moment.");
133 |
134 | if (in.empty())
135 | return;
136 |
137 | if (start / 32 != _flit_count++) {
138 | in.read();
139 | } else {
140 | if (out.full())
141 | return;
142 |
143 | auto flit = in.read();
144 | out.write(flit.data(8 * end - 1, 8 * start));
145 | if (flit.last)
146 | _flit_count = 0;
147 | }
148 | }
149 |
150 | private:
151 | ap_uint<16> _flit_count;
152 | };
153 | */
154 |
155 | class parser {
156 | public:
157 | metadata_stream out;
158 |
159 | void step(axi_data_stream& in)
160 | {
161 | #pragma HLS dataflow
162 | _enum.step(in);
163 | _extract.step(_enum.out);
164 | ntl::link(_extract.out, out);
165 | }
166 |
167 | private:
168 | ntl::enumerate _enum;
169 | extract_metadata _extract;
170 | };
171 |
--------------------------------------------------------------------------------
/ntl/axi_data.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include
29 | #include
30 | #include
31 |
32 | namespace ntl {
33 | struct raw_axi_data {
34 | ap_uint<256> data;
35 | ap_uint<32> keep;
36 | ap_uint<1> last;
37 | };
38 |
39 | struct axi_data : public boost::equality_comparable {
40 | static const int data_bits = 256;
41 | static const int data_bytes = data_bits / 8;
42 |
43 | ap_uint data;
44 | ap_uint keep;
45 | ap_uint<1> last;
46 |
47 | axi_data() {}
48 | axi_data(const ap_uint& data, const ap_uint& keep, bool last) :
49 | data(data), keep(keep), last(last) {}
50 | axi_data(const axi_data&) = default;
51 | axi_data(const raw_axi_data& o) :
52 | data(o.data), keep(o.keep), last(o.last) {}
53 |
54 | static ap_uint keep_bytes(const ap_uint<6>& valid_bytes)
55 | {
56 | return 0xffffffff ^ ((1 << (data_bytes - valid_bytes)) - 1);
57 | }
58 |
59 | void set_data(const char *d, const ap_uint<6>& valid_bytes)
60 | {
61 | keep = keep_bytes(valid_bytes);
62 | for (int byte = 0; byte < data_bytes; ++byte) {
63 | #pragma HLS unroll
64 | const char data_word = (byte < valid_bytes) ? d[byte] : 0;
65 | data(data.width - 1 - 8 * byte, data.width - 8 - 8 * byte) = data_word;
66 | }
67 | }
68 |
69 | int get_data(char *d) const
70 | {
71 | for (int byte = 0; byte < data_bytes; ++byte) {
72 | #pragma HLS unroll
73 | const uint8_t cur = data(data.width - 1 - 8 * byte, data.width - 8 - 8 * byte);
74 | if (keep[31 - byte])
75 | d[byte] = cur;
76 | else
77 | return byte;
78 | }
79 |
80 | return data_bytes;
81 | }
82 |
83 | bool operator ==(const axi_data& other) const { return data == other.data && keep == other.keep && last == other.last; }
84 |
85 | static const int width = data_bits + data_bytes + 1;
86 |
87 | axi_data(const ap_uint d) :
88 | data(d(255 + data_bytes + 1, data_bytes + 1)),
89 | keep(d(data_bytes, 1)),
90 | last(d(0, 0))
91 | {}
92 |
93 | operator ap_uint() const
94 | {
95 | #pragma HLS inline
96 | return (data, keep, last);
97 | }
98 |
99 | operator raw_axi_data() const
100 | {
101 | #pragma HLS inline
102 | return raw_axi_data{data, keep, last};
103 | }
104 | };
105 |
106 | static inline std::ostream& operator <<(std::ostream& out, const axi_data& d) {
107 | return out << "axi_data(" << std::hex << d.data << ", keep=" << d.keep << (d.last ? ", last)" : ")");
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/ntl/constant.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace ntl {
4 | template
5 | class constant_stream
6 | {
7 | public:
8 | constant_stream(const T& value) : value(value) {}
9 |
10 | template
11 | void step(Stream& out, bool enabled = true)
12 | {
13 | if (enabled && !out.full())
14 | out.write(value);
15 | }
16 |
17 | private:
18 | T value;
19 | };
20 |
21 | template
22 | constant_stream constant(const T& value)
23 | {
24 | return constant_stream(value);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ntl/constexpr.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | namespace ntl {
29 | constexpr size_t log2(size_t n)
30 | {
31 | return (n < 2) ? 0 : 1 + log2((n + 1) / 2);
32 | }
33 |
34 | template constexpr
35 | T const& max(T const& a, T const& b) {
36 | return a > b ? a : b;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ntl/consume.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | namespace ntl {
29 |
30 | class consume_stream
31 | {
32 | public:
33 | template
34 | void step(Stream& in, bool enabled = true)
35 | {
36 | #pragma HLS pipeline enable_flush
37 | if (!enabled)
38 | return;
39 |
40 | if (in.empty())
41 | return;
42 |
43 | in.read();
44 | }
45 | };
46 |
47 | template
48 | void consume(Stream& in, bool enabled = true)
49 | {
50 | #pragma HLS inline region
51 | consume_stream().step(in, enabled);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ntl/context_manager.hpp:
--------------------------------------------------------------------------------
1 | /* * Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
2 | * All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without modification,
5 | * are permitted provided that the following conditions are met:
6 | *
7 | * * Redistributions of source code must retain the above copyright notice, this
8 | * list of conditions and the following disclaimer.
9 | * * Redistributions in binary form must reproduce the above copyright notice,
10 | * this list of conditions and the following disclaimer in the documentation and/or
11 | * other materials provided with the distribution.
12 | *
13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | */
24 |
25 | #pragma once
26 |
27 | #include
28 |
29 | #include "gateway.hpp"
30 | #include "stream.hpp"
31 |
32 | namespace ntl {
33 | template
34 | class base_context_manager {
35 | public:
36 | typedef ap_uint index_t;
37 | static const size_t size = 1 << log_size;
38 |
39 | base_context_manager() {}
40 |
41 | bool valid_index(uint32_t index)
42 | {
43 | return index < (1 << log_size);
44 | }
45 |
46 | int gateway_set(uint32_t index)
47 | {
48 | #pragma HLS inline
49 | if (!valid_index(index))
50 | return GW_FAIL;
51 |
52 | if (updates.full())
53 | return GW_BUSY;
54 |
55 | updates.write(std::make_tuple(index, gateway_context));
56 | return GW_DONE;
57 | }
58 |
59 | context_t& operator[](index_t index)
60 | {
61 | #pragma HLS inline
62 | return contexts[index];
63 | }
64 |
65 | const context_t& operator[](index_t index) const
66 | {
67 | #pragma HLS inline
68 | return contexts[index];
69 | }
70 |
71 | /* Return true when accessing the array for the gateway */
72 | bool update()
73 | {
74 | #pragma HLS inline
75 | if (updates.empty())
76 | return false;
77 |
78 | index_t index;
79 | context_t context;
80 |
81 | std::tie(index, context) = updates.read();
82 | contexts[index] = context;
83 | return true;
84 | }
85 |
86 | context_t gateway_context;
87 | context_t contexts[size];
88 |
89 | private:
90 |
91 | stream > updates;
92 | };
93 |
94 |
95 | template
96 | class context_manager {
97 | public:
98 | typedef ap_uint index_t;
99 | static const size_t size = 1 << log_size;
100 |
101 | context_manager() : gateway_state(IDLE) {}
102 |
103 | bool valid_index(uint32_t index)
104 | {
105 | return index < (1 << log_size);
106 | }
107 |
108 | int gateway_query(uint32_t index)
109 | {
110 | #pragma HLS inline
111 | switch (gateway_state) {
112 | case IDLE:
113 | if (!valid_index(index))
114 | return GW_FAIL;
115 |
116 | if (queries.full())
117 | return GW_BUSY;
118 |
119 | queries.write(index);
120 | gateway_state = QUERY_SENT;
121 | return GW_BUSY;
122 | case QUERY_SENT:
123 | if (responses.empty())
124 | return GW_BUSY;
125 | gateway_context = responses.read();
126 | gateway_state = IDLE;
127 | return GW_DONE;
128 | default:
129 | return GW_FAIL;
130 | }
131 | }
132 |
133 | /* Read-modify-write operation from the gateway */
134 | template
135 | int gateway_rmw(uint32_t index, F f)
136 | {
137 | #pragma HLS inline
138 | switch (gateway_state) {
139 | case IDLE:
140 | if (!valid_index(index))
141 | return GW_FAIL;
142 |
143 | if (queries.full())
144 | return GW_BUSY;
145 |
146 | queries.write(index);
147 | gateway_state = QUERY_SENT;
148 | return GW_BUSY;
149 | case QUERY_SENT:
150 | if (responses.empty())
151 | return GW_BUSY;
152 |
153 | gateway_context = responses.read();
154 | gateway_state = UPDATE;
155 | /* Fall through */
156 | case UPDATE:
157 | if (updates.full())
158 | return GW_BUSY;
159 |
160 | updates.write(std::make_tuple(index, f(gateway_context)));
161 | gateway_state = IDLE;
162 | return GW_DONE;
163 |
164 | default:
165 | return GW_FAIL;
166 | }
167 | }
168 |
169 | template
170 | int gateway_access_field(uint32_t index, int *value, bool read)
171 | {
172 | #pragma HLS inline
173 | int ret;
174 | if (read) {
175 | ret = gateway_query(index);
176 | if (ret == GW_DONE)
177 | *value = gateway_context.*field;
178 | return ret;
179 | } else {
180 | return gateway_rmw(index, [value](context_t c) -> context_t {
181 | c.*field = *value;
182 | return c;
183 | });
184 | }
185 | }
186 |
187 | /* Return true when accessing the array for the gateway */
188 | bool update()
189 | {
190 | #pragma HLS inline
191 | std::tuple update;
192 | if (updates.read_nb(update)) {
193 | index_t index;
194 | context_t context;
195 |
196 | std::tie(index, context) = update;
197 | contexts[index] = context;
198 | return true;
199 | }
200 | if (!queries.empty() && !responses.full()) {
201 | index_t index;
202 | queries.read_nb(index);
203 | responses.write_nb(contexts[index]);
204 | return true;
205 | }
206 |
207 | return false;
208 | }
209 |
210 | int gateway_set(uint32_t index)
211 | {
212 | #pragma HLS inline
213 | if (!valid_index(index))
214 | return GW_FAIL;
215 |
216 | if (updates.full())
217 | return GW_BUSY;
218 |
219 | updates.write(std::make_tuple(index, gateway_context));
220 | return GW_DONE;
221 | }
222 |
223 | context_t& operator[](index_t index)
224 | {
225 | #pragma HLS inline
226 | return contexts[index];
227 | }
228 |
229 | const context_t& operator[](index_t index) const
230 | {
231 | #pragma HLS inline
232 | return contexts[index];
233 | }
234 |
235 | context_t gateway_context;
236 | context_t contexts[size];
237 |
238 | private:
239 | enum { IDLE, QUERY_SENT, UPDATE } gateway_state;
240 |
241 | hls::stream queries;
242 | hls::stream responses;
243 | hls::stream > updates;
244 | };
245 | } // namespace ntl
246 |
--------------------------------------------------------------------------------
/ntl/counter.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "fold.hpp"
29 |
30 | #include
31 | #include
32 |
33 | namespace ntl {
34 | template >
35 | class counter : public ntl::fold
36 | {
37 | public:
38 | typedef ntl::fold base;
39 | typedef typename base::in_t in_t;
40 | counter() : base(-1) {}
41 |
42 | void step(in_t& in)
43 | {
44 | #pragma HLS pipeline enable_flush
45 | base::step(in, [](Counter cnt, const T& t) {
46 | return ++cnt;
47 | });
48 | }
49 | };
50 |
51 | template
52 | class maxed_int : public ap_uint, public boost::incrementable>
53 | {
54 | public:
55 | typedef ap_uint base;
56 | maxed_int() : base() {}
57 | maxed_int(const base& b) : base(b) {}
58 | #define CTOR(TYPE) \
59 | INLINE maxed_int(TYPE v) : base(v) {}
60 | CTOR(bool)
61 | CTOR(signed char)
62 | CTOR(unsigned char)
63 | CTOR(short)
64 | CTOR(unsigned short)
65 | CTOR(int)
66 | CTOR(unsigned int)
67 | CTOR(long)
68 | CTOR(unsigned long)
69 | CTOR(unsigned long long)
70 | CTOR(long long)
71 | CTOR(half)
72 | CTOR(float)
73 | CTOR(double)
74 | CTOR(const char*)
75 | #undef CTOR
76 |
77 | maxed_int& operator++()
78 | {
79 | if (*this != limit)
80 | ap_uint::operator++(*this);
81 | return *this;
82 | }
83 | };
84 | }
85 |
--------------------------------------------------------------------------------
/ntl/dup.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include
29 | #include
30 |
31 | namespace ntl {
32 |
33 | template
34 | class dup
35 | {
36 | public:
37 | std::array, n> _streams;
38 |
39 | template
40 | void step(InputStream& in)
41 | {
42 | #pragma HLS pipeline enable_flush
43 | if (in.empty())
44 | return;
45 |
46 | for (auto& out : _streams) {
47 | if (out.full())
48 | return;
49 | }
50 |
51 | auto flit = in.read();
52 | for (auto& out : _streams) {
53 | out.write(flit);
54 | }
55 | }
56 | };
57 | }
58 |
--------------------------------------------------------------------------------
/ntl/enumerate.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "counter.hpp"
29 | #include "dup.hpp"
30 | #include "zip.hpp"
31 |
32 | namespace ntl {
33 |
34 | template >
35 | class enumerate
36 | {
37 | public:
38 | typedef std::tuple tuple_t;
39 | typedef stream out_t;
40 | out_t out;
41 |
42 | template
43 | void step(InputStream& in)
44 | {
45 | #pragma HLS inline
46 | dup.step(in);
47 | _counter.step(dup._streams[0]);
48 | zip.step(_counter.out, dup._streams[1]);
49 | link(zip.out, out);
50 | }
51 | private:
52 | ntl::dup dup;
53 | counter _counter;
54 | ntl::zip zip;
55 | };
56 |
57 | template
58 | class enum_first : public enumerate>
59 | {
60 | };
61 | }
62 |
--------------------------------------------------------------------------------
/ntl/fold.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "last.hpp"
29 | #include
30 |
31 | namespace ntl {
32 |
33 | template
34 | class fold
35 | {
36 | public:
37 | typedef stream in_t;
38 | typedef stream out_t;
39 | out_t out;
40 |
41 | explicit fold(const Out& initial) : _initial(initial), _current(initial)
42 | {}
43 |
44 | template
45 | void step(in_t& in, Func&& f)
46 | {
47 | #pragma HLS inline region
48 | if (in.empty() || out.full())
49 | return;
50 |
51 | auto flit = in.read();
52 | auto next = f(_current, flit);
53 | if (out_every_flit || last(flit))
54 | out.write(next);
55 | _current = last(flit) ? _initial : next;
56 | }
57 | private:
58 | const Out _initial;
59 | Out _current;
60 | };
61 | }
62 |
--------------------------------------------------------------------------------
/ntl/gateway.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "macros.hpp"
29 |
30 | #include
31 |
32 | #define GATEWAY_OFFSET(gateway, offset_cmd, offset_data, offset_done) \
33 | DO_PRAGMA_SYN(HLS interface s_axilite port=gateway.cmd offset=offset_cmd) \
34 | DO_PRAGMA_SYN(HLS interface s_axilite port=gateway.data offset=offset_data) \
35 | DO_PRAGMA_SYN(HLS interface s_axilite port=gateway.done offset=offset_done)
36 |
37 | namespace ntl {
38 | enum {
39 | GW_FAIL = (-1),
40 | GW_DONE = 0,
41 | GW_BUSY = 1,
42 | };
43 |
44 | template
45 | struct gateway_registers {
46 | gateway_registers() : cmd({0, 0}), data(), done(0) {}
47 |
48 | struct {
49 | ap_uint<31> addr;
50 | ap_uint<1> go; // Bit 31
51 | } cmd;
52 |
53 | T data;
54 |
55 | ap_uint<1> done;
56 | };
57 |
58 | template
59 | class gateway_impl {
60 | public:
61 | gateway_impl() : axilite_gateway_done(false) {}
62 |
63 | template
64 | void gateway(gateway_registers& r, Func&& f) {
65 | #pragma HLS pipeline enable_flush ii=1
66 | DO_PRAGMA_SYN(HLS data_pack variable=r.cmd)
67 | if (r.cmd.go && !axilite_gateway_done) {
68 | int res = f(r.cmd.addr, r.data);
69 | if (res != GW_BUSY) {
70 | axilite_gateway_done = true;
71 | r.done = 1;
72 | }
73 | } else if (!r.cmd.go && axilite_gateway_done) {
74 | axilite_gateway_done = false;
75 | r.done = 0;
76 | }
77 | }
78 |
79 | private:
80 | bool axilite_gateway_done;
81 | };
82 | }
83 |
--------------------------------------------------------------------------------
/ntl/last.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "last.hpp"
29 |
30 | namespace ntl {
31 | template
32 | inline bool last(const T& t)
33 | {
34 | return t.last;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ntl/link.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | namespace ntl {
29 |
30 | template
31 | void link(InputStream& in, OutputStream& out)
32 | {
33 | #pragma HLS pipeline enable_flush
34 | typedef typename stream_element::type out_element_type;
35 |
36 | if (in.empty() || out.full())
37 | return;
38 |
39 | out.write(out_element_type(in.read()));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ntl/macros.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #define PRAGMA_SUB(x) _Pragma(#x)
29 | /* Use DO_PRAGMA to be able to have C preprocessor expansion in a pragma */
30 | #define DO_PRAGMA(x) PRAGMA_SUB(x)
31 |
32 | /* RTL/C co-simulation doesn't work well with certain definitions, so make them
33 | * conditional */
34 | #ifdef SIMULATION_BUILD
35 | # define _PragmaSyn(x)
36 | # define DO_PRAGMA_SYN(x)
37 | # define _PragmaSim(x) _Pragma(x)
38 | # define DO_PRAGMA_SIM(x) DO_PRAGMA(x)
39 | #else
40 | # define _PragmaSyn(x) _Pragma(x)
41 | # define DO_PRAGMA_SYN(x) DO_PRAGMA(x)
42 | # define _PragmaSim(x)
43 | # define DO_PRAGMA_SIM(x)
44 | #endif
45 |
46 | #define ALIGN(x,a) __ALIGN_MASK(x,(a)-1)
47 | #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
48 |
49 |
--------------------------------------------------------------------------------
/ntl/map.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | namespace ntl {
29 |
30 | template
31 | void map(InputStream& in, OutputStream& out, Func&& f)
32 | {
33 | #pragma HLS pipeline enable_flush
34 | if (in.empty() || out.full())
35 | return;
36 |
37 | out.write(f(in.read()));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ntl/maybe.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "pack.hpp"
29 |
30 | namespace ntl {
31 |
32 | template
33 | class maybe {
34 | public:
35 | maybe(bool valid, const Value& v) : _valid(valid), _value(v) {}
36 | maybe(const Value& v) : _valid(true), _value(v) {}
37 | maybe() : _valid(false) {}
38 |
39 | bool valid() const { return _valid; }
40 | const Value& value() const { return _value; }
41 |
42 | operator bool() const { return valid(); }
43 |
44 | void reset() { _valid = false; }
45 | private:
46 | bool _valid;
47 | Value _value;
48 | };
49 |
50 | template
51 | maybe make_maybe(bool valid, const Value& v)
52 | {
53 | return maybe(valid, v);
54 | }
55 |
56 | template
57 | maybe make_maybe(const Value& v)
58 | {
59 | return maybe(true, v);
60 | }
61 |
62 | template
63 | struct pack > {
64 | static const int width = 1 + pack::width;
65 | static ap_uint to_int(const maybe& e) {
66 | return (ap_uint<1>(e.valid()), pack::to_int(e.value()));
67 | }
68 |
69 | static maybe from_int(const ap_uint& d) {
70 | bool valid = d(width - 1, width - 1);
71 | T value = pack::from_int(d(width - 2, 0));
72 | return make_maybe(valid, value);
73 | }
74 | };
75 | }
76 |
--------------------------------------------------------------------------------
/ntl/memory.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2019 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include "macros.hpp"
29 | #include "stream.hpp"
30 | #include "produce.hpp"
31 | #include "consume.hpp"
32 | #include "link.hpp"
33 |
34 | namespace ntl {
35 |
36 | template
37 | class memory {
38 | public:
39 | enum {
40 | interface_width = _interface_width,
41 | };
42 | typedef ap_uint<512> value_t;
43 | typedef ap_uint index_t;
44 |
45 | /* TODO pass other auxilary signals */
46 |
47 | stream ar;
48 | stream r;
49 | stream aw;
50 | stream w;
51 | stream b;
52 |
53 | void write(index_t index, value_t value)
54 | {
55 | #pragma HLS inline
56 | aw.write(index);
57 | w.write(value);
58 | }
59 |
60 | void post_read(index_t index)
61 | {
62 | #pragma HLS inline
63 | ar.write(index);
64 | }
65 |
66 | bool has_write_response()
67 | {
68 | #pragma HLS inline
69 | return !b.empty();
70 | }
71 |
72 | bool get_write_response()
73 | {
74 | #pragma HLS inline
75 | return b.read();
76 | }
77 |
78 | bool has_read_response()
79 | {
80 | #pragma HLS inline
81 | return !r.empty();
82 | }
83 |
84 | value_t get_read_response()
85 | {
86 | #pragma HLS inline
87 | return r.read();
88 | }
89 | };
90 |
91 | template
92 | static inline void link(memory& in, memory& out)
93 | {
94 | #pragma HLS inline
95 | link(out.aw, in.aw);
96 | link(out.w, in.w);
97 | link(out.ar, in.ar);
98 | link(in.b, out.b);
99 | link(in.r, out.r);
100 | }
101 |
102 | /* In cases the memory interface is not used, this function convinces HLS
103 | * that it is used, and set the right stream directions. */
104 | class memory_unused
105 | {
106 | public:
107 | memory_unused() : dummy_update("dummy_update") {}
108 |
109 | template
110 | void step(memory& m)
111 | {
112 | #pragma HLS inline
113 | bool dummy = false;
114 |
115 | if (!dummy_update.full())
116 | dummy_update.write(false);
117 |
118 | if (!dummy_update.empty())
119 | dummy = dummy_update.read();
120 |
121 | ntl::produce(m.ar, dummy);
122 | ntl::produce(m.aw, dummy);
123 | ntl::produce(m.w, dummy);
124 | ntl::consume(m.r, dummy);
125 | ntl::consume(m.b, dummy);
126 | }
127 |
128 | private:
129 | /* Dummy boolean to make it easier to define unused HLS stream direction. Pass it
130 | * to produce/consume function to trick HLS into thinking they are used. */
131 | stream dummy_update;
132 | };
133 | }
134 |
135 | #define NTL_MEMORY_INTERFACE_PRAGMA(memory) \
136 | DO_PRAGMA_SYN(HLS interface axis port=&memory.ar) \
137 | DO_PRAGMA_SYN(HLS interface axis port=&memory.r) \
138 | DO_PRAGMA_SYN(HLS interface axis port=&memory.aw) \
139 | DO_PRAGMA_SYN(HLS interface axis port=&memory.w) \
140 | DO_PRAGMA_SYN(HLS interface axis port=&memory.b)
141 |
--------------------------------------------------------------------------------
/ntl/pack.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016-2018 Haggai Eran, Gabi Malka, Lior Zeno, Maroun Tork
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include
29 | #include
30 |
31 | namespace ntl {
32 | template
33 | struct pack {
34 | static const int width = T::width;
35 |
36 | static ap_uint to_int(const T& e) {
37 | return e;
38 | }
39 |
40 | static T from_int(const ap_uint& d) {
41 | return T(d);
42 | }
43 | };
44 |
45 | template
46 | struct pack > {
47 | static const int width = pack::width + pack::width;
48 |
49 | typedef std::tuple type;
50 |
51 | static ap_uint to_int(const type& e) {
52 | return (pack::to_int(std::get<0>(e)),
53 | pack::to_int(std::get<1>(e)));
54 | }
55 |
56 | static type from_int(const ap_uint& d) {
57 | T1 t1 = pack::from_int(d(width - 1, pack::width));
58 | T2 t2 = pack::from_int(d(pack::width - 1, 0));
59 | return std::make_tuple(t1, t2);
60 | }
61 | };
62 |
63 | template
64 | ap_uint::width> pack_to_int(const T& t)
65 | {
66 | return pack::to_int(t);
67 | }
68 |
69 | template
70 | T unpack(const ap_uint::width>& d)
71 | {
72 | return pack::from_int(d);
73 | }
74 |
75 | template
76 | class pack_stream
77 | {
78 | public:
79 | typedef T type;
80 | static const int width = pack::width;
81 | typedef ap_uint raw_t;
82 |
83 | pack_stream() {}
84 | pack_stream(const char *name) : raw_s(name) {}
85 |
86 | bool full()
87 | {
88 | #pragma HLS inline
89 | return raw_s.full();
90 | }
91 |
92 | bool empty()
93 | {
94 | #pragma HLS inline
95 | return raw_s.empty();
96 | }
97 |
98 | void write(const type& value)
99 | {
100 | #pragma HLS inline
101 | raw_s.write(pack_to_int(value));
102 | }
103 |
104 | bool write_nb(const type& value)
105 | {
106 | #pragma HLS inline
107 | return raw_s.write_nb(pack_to_int(value));
108 | }
109 |
110 | T read()
111 | {
112 | #pragma HLS inline
113 | return unpack(raw_s.read());
114 | }
115 |
116 | bool read_nb(type& value)
117 | {
118 | #pragma HLS inline
119 | raw_t raw;
120 | bool ret = raw_s.read_nb(raw);
121 | if (ret)
122 | value = unpack(raw);
123 | return ret;
124 | }
125 | private:
126 | hls::stream raw_s;
127 | };
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/ntl/peek_stream.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2019 Haggai Eran
3 | // All rights reserved.
4 | //
5 | // Redistribution and use in source and binary forms, with or without modification,
6 | // are permitted provided that the following conditions are met:
7 | //
8 | // * Redistributions of source code must retain the above copyright notice, this
9 | // list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation and/or
12 | // other materials provided with the distribution.
13 | //
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | //
25 |
26 | #pragma once
27 |
28 | #include
29 |
30 | #include