• 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 // This timing interface enables and targets ARM registers to enable clock cycle
16 // counting. The documentation can be found here:
17 // https://developer.arm.com/documentation/ddi0337/e/System-Debug/DWT?lang=en
18 // https://developer.arm.com/documentation/ddi0337/e/CEGHJDCF
19 
20 #pragma once
21 
22 #include <cstdint>
23 
24 #include "pw_perf_test/internal/duration_unit.h"
25 
26 namespace pw::perf_test::internal::backend {
27 
28 // Creates a reference to the DWT Control unit
29 inline volatile uint32_t& kDwtCtrl =
30     *reinterpret_cast<volatile uint32_t*>(0xE0001000);
31 // Creates a reference to the memory address in which the DWT register stores
32 // clock incrementations
33 inline volatile uint32_t& kDwtCcynt =
34     *reinterpret_cast<volatile uint32_t*>(0xE0001004);
35 // Creates a reference to the location of the Debug Exception and Monitor
36 // Control register.
37 inline volatile uint32_t& kDemcr =
38     *reinterpret_cast<volatile uint32_t*>(0xE000EDFC);
39 
40 using Timestamp = uint32_t;
41 
42 inline constexpr DurationUnit kDurationUnit = DurationUnit::kClockCycle;
43 
TimerPrepare()44 [[nodiscard]] inline bool TimerPrepare() {
45   kDemcr |= 0x01000000;    // Enables the DWT control register
46   kDwtCtrl |= 0x00000001;  // Enables the DWT clock
47   kDwtCcynt = 0x00000000;  // Intializes the clock to 0
48   return (kDemcr & 0x01000000) && (kDwtCtrl & 0x00000001);
49 }
50 
51 // Disables the DWT clock
TimerCleanup()52 inline void TimerCleanup() { kDwtCtrl &= ~0x00000001; }
53 
GetCurrentTimestamp()54 inline Timestamp GetCurrentTimestamp() { return kDwtCcynt; }
55 
56 // Warning: this duration will overflow if the duration is greater that 2^32
57 // clock cycles.
GetDuration(Timestamp begin,Timestamp end)58 inline int64_t GetDuration(Timestamp begin, Timestamp end) {
59   return static_cast<int64_t>(end - begin);
60 }
61 
62 }  // namespace pw::perf_test::internal::backend
63