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
37using namespace std;
38
39namespace ue2 {
40
41template<typename T>
42static
43void 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
50static
51void 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
58static
59void 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
66scatter_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
99u32 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
110void 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