• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include <cstring>
16 
17 #include "pw_bloat/bloat_this_binary.h"
18 #include "pw_log/log.h"
19 #include "pw_preprocessor/compiler.h"
20 #include "pw_span/span.h"
21 
22 #ifdef USE_CRC16_CHECKSUM
23 #include "pw_checksum/crc16_ccitt.h"
24 using TheChecksum = pw::checksum::Crc16Ccitt;
25 #endif
26 
27 #ifdef USE_CRC32_8BIT_CHECKSUM
28 #include "pw_checksum/crc32.h"
29 using TheChecksum = pw::checksum::Crc32EightBit;
30 #endif
31 
32 #ifdef USE_CRC32_4BIT_CHECKSUM
33 #include "pw_checksum/crc32.h"
34 using TheChecksum = pw::checksum::Crc32FourBit;
35 #endif
36 
37 #ifdef USE_CRC32_1BIT_CHECKSUM
38 #include "pw_checksum/crc32.h"
39 using TheChecksum = pw::checksum::Crc32OneBit;
40 #endif
41 
42 namespace pw::checksum {
43 
44 #ifdef USE_NOOP_CHECKSUM
45 class NoOpChecksum {
46  public:
Calculate(span<const std::byte>)47   static uint32_t Calculate(span<const std::byte>) { return arbitrary_value; }
48 
49   // Don't inline to prevent the compiler from optimizing out the checksum.
Update(span<const std::byte>)50   PW_NO_INLINE void Update(span<const std::byte>) {}
51 
Update(std::byte)52   PW_NO_INLINE void Update(std::byte) {}
53 
value() const54   PW_NO_INLINE uint32_t value() const { return arbitrary_value; }
clear()55   void clear() {}
56 
57  private:
58   // static volatile uint32_t arbitrary_value;
59   const static uint32_t arbitrary_value = 10;
60 };
61 using TheChecksum = NoOpChecksum;
62 #endif
63 
64 // Fletcher16 is a simple checksum that shouldn't be used in production, but is
65 // interesting from a size comparison perspective.
66 #ifdef USE_FLETCHER16_CHECKSUM
67 class Fletcher16 {
68  public:
Fletcher16()69   Fletcher16() : sum1_(0), sum2_(0) {}
70 
71   // Don't inline to prevent the compiler from optimizing out the checksum.
Calculate(span<const std::byte> data)72   PW_NO_INLINE static uint32_t Calculate(span<const std::byte> data) {
73     Fletcher16 checksum;
74     checksum.Update(data);
75     return checksum.value();
76   }
77 
Update(span<const std::byte> data)78   PW_NO_INLINE void Update(span<const std::byte> data) {
79     for (std::byte b : data) {
80       sum1_ = static_cast<uint16_t>((sum1_ + static_cast<uint16_t>(b)) % 255u);
81       sum2_ = static_cast<uint16_t>((sum2_ + sum1_) % 255u);
82     }
83   }
Update(std::byte)84   PW_NO_INLINE void Update(std::byte) {}
value() const85   PW_NO_INLINE uint32_t value() const {
86     return static_cast<uint32_t>(sum2_) << 8 | sum1_;
87   };
clear()88   void clear() {}
89 
90  private:
91   uint16_t sum1_ = 0;
92   uint16_t sum2_ = 0;
93 };
94 using TheChecksum = Fletcher16;
95 #endif
96 
97 char buffer[128];
98 char* volatile get_buffer = buffer;
99 volatile unsigned get_size;
100 
RunChecksum()101 int RunChecksum() {
102   // Trick the optimizer and also satisfy the type checker.
103   get_size = sizeof(buffer);
104   char* local_buffer = get_buffer;
105   unsigned local_size = get_size;
106 
107   // Calculate the checksum and stash it in a volatile variable so the compiler
108   // can't optimize it out.
109   TheChecksum checksum;
110   checksum.Update(pw::as_bytes(span(local_buffer, local_size)));
111   uint32_t value = static_cast<uint32_t>(checksum.value());
112   *get_buffer = static_cast<char>(value);
113   return 0;
114 }
115 
116 }  // namespace pw::checksum
117 
main()118 int main() {
119   pw::bloat::BloatThisBinary();
120   return pw::checksum::RunChecksum();
121 }
122