1 | /* |
2 | * Copyright (c) 2015-2017, Intel Corporation |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions are met: |
6 | * |
7 | * * Redistributions of source code must retain the above copyright notice, |
8 | * this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of Intel Corporation nor the names of its contributors |
13 | * may be used to endorse or promote products derived from this software |
14 | * without specific prior written permission. |
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 |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | #include "rose_build_scatter.h" |
30 | #include "ue2common.h" |
31 | #include "util/container.h" |
32 | #include "util/multibit_build.h" |
33 | |
34 | #include <cstring> // memset |
35 | #include <set> |
36 | |
37 | using namespace std; |
38 | |
39 | namespace ue2 { |
40 | |
41 | template<typename T> |
42 | static |
43 | void rebase(vector<T> *p, u32 adj) { |
44 | for (typename vector<T>::iterator it = p->begin(); it != p->end(); ++it) { |
45 | DEBUG_PRINTF("=%u+%u\n" , it->offset, adj); |
46 | it->offset += adj; |
47 | } |
48 | } |
49 | |
50 | static |
51 | void rebase(scatter_plan_raw *raw, u32 adj) { |
52 | rebase(&raw->p_u64a, adj); |
53 | rebase(&raw->p_u32, adj); |
54 | rebase(&raw->p_u16, adj); |
55 | rebase(&raw->p_u8, adj); |
56 | } |
57 | |
58 | static |
59 | void merge_in(scatter_plan_raw *out, const scatter_plan_raw &in) { |
60 | insert(&out->p_u64a, out->p_u64a.end(), in.p_u64a); |
61 | insert(&out->p_u32, out->p_u32.end(), in.p_u32); |
62 | insert(&out->p_u16, out->p_u16.end(), in.p_u16); |
63 | insert(&out->p_u8, out->p_u8.end(), in.p_u8); |
64 | } |
65 | |
66 | scatter_plan_raw buildStateScatterPlan(u32 role_state_offset, |
67 | u32 role_state_count, u32 left_array_count, u32 left_prefix_count, |
68 | const RoseStateOffsets &stateOffsets, bool streaming, |
69 | u32 leaf_array_count, u32 outfix_begin, u32 outfix_end) { |
70 | scatter_plan_raw out; |
71 | |
72 | /* init role array */ |
73 | scatter_plan_raw spr_role; |
74 | mmbBuildClearPlan(role_state_count, &spr_role); |
75 | rebase(&spr_role, role_state_offset); |
76 | merge_in(&out, spr_role); |
77 | |
78 | /* init rose array: turn on prefixes */ |
79 | u32 rose_array_offset = stateOffsets.activeLeftArray; |
80 | scatter_plan_raw spr_rose; |
81 | mmbBuildInitRangePlan(left_array_count, 0, left_prefix_count, &spr_rose); |
82 | rebase(&spr_rose, rose_array_offset); |
83 | merge_in(&out, spr_rose); |
84 | |
85 | /* suffix/outfix array */ |
86 | scatter_plan_raw spr_leaf; |
87 | if (streaming) { |
88 | mmbBuildInitRangePlan(leaf_array_count, outfix_begin, outfix_end, |
89 | &spr_leaf); |
90 | } else { |
91 | mmbBuildClearPlan(leaf_array_count, &spr_leaf); |
92 | } |
93 | rebase(&spr_leaf, stateOffsets.activeLeafArray); |
94 | merge_in(&out, spr_leaf); |
95 | |
96 | return out; |
97 | } |
98 | |
99 | u32 aux_size(const scatter_plan_raw &raw) { |
100 | u32 rv = 0; |
101 | |
102 | rv += byte_length(raw.p_u64a); |
103 | rv += byte_length(raw.p_u32); |
104 | rv += byte_length(raw.p_u16); |
105 | rv += byte_length(raw.p_u8); |
106 | |
107 | return rv; |
108 | } |
109 | |
110 | void write_out(scatter_full_plan *plan_out, void *aux_out, |
111 | const scatter_plan_raw &raw, u32 aux_base_offset) { |
112 | memset(plan_out, 0, sizeof(*plan_out)); |
113 | |
114 | #define DO_CASE(t) \ |
115 | if (!raw.p_##t.empty()) { \ |
116 | plan_out->s_##t##_offset = aux_base_offset; \ |
117 | plan_out->s_##t##_count = raw.p_##t.size(); \ |
118 | assert(ISALIGNED_N((char *)aux_out + aux_base_offset, \ |
119 | alignof(scatter_unit_##t))); \ |
120 | memcpy((char *)aux_out + aux_base_offset, raw.p_##t.data(), \ |
121 | byte_length(raw.p_##t)); \ |
122 | aux_base_offset += byte_length(raw.p_##t); \ |
123 | } |
124 | |
125 | DO_CASE(u64a); |
126 | DO_CASE(u32); |
127 | DO_CASE(u16); |
128 | DO_CASE(u8); |
129 | } |
130 | |
131 | } // namespace ue2 |
132 | |