tests, base: Added GTests for base/amo.hh
[gem5.git] / src / base / amo.test.cc
1 /*
2 * Copyright (c) 2020 The Regents of the University of California
3 * All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, 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;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <gtest/gtest.h>
32
33 #include <string>
34 #include <array>
35
36 #include "base/amo.hh"
37
38 void
39 multiply2Op(int *b, int a)
40 {
41 *b *= a;
42 }
43
44 void
45 multiply3Op(int *b, int a, int c)
46 {
47 *b *= a * c;
48 }
49
50 void
51 addSubColumns(int *b, const std::array<int, 2>& a, const std::array<int, 2>& c)
52 {
53 *b += a[0] + c[0];
54 *b -= a[1] + c[1];
55 }
56
57 TEST(AmoTest, AtomicOpMin)
58 {
59 // test with ints and strings
60 int test_int_smaller = 5;
61 int test_int_bigger = 15;
62 std::string test_string_smaller = "apple";
63 std::string test_string_bigger = "cat";
64
65 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpMin<int>(10);
66 TypedAtomicOpFunctor<std::string> *amo_op_string =
67 new AtomicOpMin<std::string>("base");
68 amo_op_int->execute(&test_int_smaller);
69 amo_op_int->execute(&test_int_bigger);
70 amo_op_string->execute(&test_string_smaller);
71 amo_op_string->execute(&test_string_bigger);
72
73 EXPECT_EQ(test_int_smaller, 5);
74 EXPECT_EQ(test_int_bigger, 10);
75 EXPECT_EQ(test_string_smaller, "apple");
76 EXPECT_EQ(test_string_bigger, "base");
77 }
78
79 TEST(AmoTest, AtomicOpMax)
80 {
81 int test_int_smaller = 5;
82 int test_int_bigger = 15;
83 std::string test_string_smaller = "apple";
84 std::string test_string_bigger = "cat";
85
86 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpMax<int>(10);
87 TypedAtomicOpFunctor<std::string> *amo_op_string =
88 new AtomicOpMax<std::string>("base");
89 amo_op_int->execute(&test_int_smaller);
90 amo_op_int->execute(&test_int_bigger);
91 amo_op_string->execute(&test_string_smaller);
92 amo_op_string->execute(&test_string_bigger);
93
94 EXPECT_EQ(test_int_smaller, 10);
95 EXPECT_EQ(test_int_bigger, 15);
96 EXPECT_EQ(test_string_smaller, "base");
97 EXPECT_EQ(test_string_bigger, "cat");
98 }
99
100 TEST(AmoTest, AtomicOpDec)
101 {
102 int test_int = 10;
103 char test_char = 'c';
104
105 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpDec<int>();
106 TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpDec<char>();
107 amo_op_int->execute(&test_int);
108 amo_op_char->execute(&test_char);
109
110 EXPECT_EQ(test_int, 9);
111 EXPECT_EQ(test_char, 'b');
112 }
113
114 TEST(AmoTest, AtomicOpInc)
115 {
116 int test_int = 10;
117 char test_char = 'c';
118
119 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpInc<int>();
120 TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpInc<char>();
121 amo_op_int->execute(&test_int);
122 amo_op_char->execute(&test_char);
123
124 EXPECT_EQ(test_int, 11);
125 EXPECT_EQ(test_char, 'd');
126 }
127
128 TEST(AmoTest, AtomicOpSub)
129 {
130 int test_int = 10;
131 char test_char = 'c';
132
133 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpSub<int>(2);
134 TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpSub<char>('a');
135 amo_op_int->execute(&test_int);
136 amo_op_char->execute(&test_char);
137
138 EXPECT_EQ(test_int, 8);
139 EXPECT_EQ(test_char, 2);
140 }
141
142 TEST(AmoTest, AtomicOpAdd)
143 {
144 int test_int = 10;
145 char test_char = 'c';
146
147 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpAdd<int>(2);
148 TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpAdd<char>(2);
149 amo_op_int->execute(&test_int);
150 amo_op_char->execute(&test_char);
151
152 EXPECT_EQ(test_int, 12);
153 EXPECT_EQ(test_char, 'e');
154 }
155
156 TEST(AmoTest, AtomicOpExch)
157 {
158 int test_int = 10;
159 char test_char = 'c';
160
161 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpExch<int>(2);
162 TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpExch<char>('a');
163 amo_op_int->execute(&test_int);
164 amo_op_char->execute(&test_char);
165
166 EXPECT_EQ(test_int, 2);
167 EXPECT_EQ(test_char, 'a');
168 }
169
170 TEST(AmoTest, AtomicOpXor)
171 {
172 int test_int = 10;
173 char test_char = 'c';
174
175 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpXor<int>(2);
176 TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpXor<char>('a');
177 amo_op_int->execute(&test_int);
178 amo_op_char->execute(&test_char);
179
180 EXPECT_EQ(test_int, 8); // 1010 ^ 0010 = 1000
181 EXPECT_EQ(test_char, 2); // 99 ^ 97 = 2
182 }
183
184 TEST(AmoTest, AtomicOpOr)
185 {
186 int test_int = 8;
187 bool test_bool = true;
188
189 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpOr<int>(2);
190 TypedAtomicOpFunctor<bool> *amo_op_bool = new AtomicOpOr<bool>(false);
191 amo_op_int->execute(&test_int);
192 amo_op_bool->execute(&test_bool);
193
194 EXPECT_EQ(test_int, 10);
195 EXPECT_EQ(test_bool, true);
196 }
197
198 TEST(AmoTest, AtomicOpAnd)
199 {
200 int test_int = 10;
201 char test_char = 'c';
202
203 TypedAtomicOpFunctor<int> *amo_op_int = new AtomicOpAnd<int>(6);
204 TypedAtomicOpFunctor<char> *amo_op_char = new AtomicOpAnd<char>('a');
205 amo_op_int->execute(&test_int);
206 amo_op_char->execute(&test_char);
207
208 EXPECT_EQ(test_int, 2);
209 EXPECT_EQ(test_char, 'a');
210 }
211
212 TEST(AmoTest, AtomicGeneric2Op)
213 {
214 int test_int = 9;
215
216 TypedAtomicOpFunctor<int> *amo_op_int =
217 new AtomicGeneric2Op<int>(9, multiply2Op);
218 amo_op_int->execute(&test_int);
219
220 EXPECT_EQ(test_int, 81);
221 }
222
223 TEST(AmoTest, AtomicGeneric3Op)
224 {
225 int test_int = 2;
226
227 TypedAtomicOpFunctor<int> *amo_op_int =
228 new AtomicGeneric3Op<int>(4, 3, multiply3Op);
229 amo_op_int->execute(&test_int);
230
231 EXPECT_EQ(test_int, 24);
232 }
233
234 TEST(AmoTest, AtomicGenericPair3Op)
235 {
236 int test_int = 5;
237
238 std::array<int, 2> a = {6, 3};
239 std::array<int, 2> c = {10, 8};
240 TypedAtomicOpFunctor<int> *amo_op_int =
241 new AtomicGenericPair3Op<int>(a, c, addSubColumns);
242 amo_op_int->execute(&test_int);
243
244 EXPECT_EQ(test_int, 10);
245 }