SST 16.1.0
Structural Simulation Toolkit
coreTest_ClockerComponent.h
1// Copyright 2009-2026 NTESS. Under the terms
2// of Contract DE-NA0003525 with NTESS, the U.S.
3// Government retains certain rights in this software.
4//
5// Copyright (c) 2009-2026, NTESS
6// All rights reserved.
7//
8// This file is part of the SST software package. For license
9// information, see the LICENSE file in the top level directory of the
10// distribution.
11
12#ifndef SST_CORE_CORETEST_CLOCKERCOMPONENT_H
13#define SST_CORE_CORETEST_CLOCKERCOMPONENT_H
14
15#include "sst/core/component.h"
16#include "sst/core/subcomponent.h"
17
18#include <cstdint>
19#include <string>
20
21namespace SST::CoreTestClockerComponent {
22
24
25/**
26 API for SubComponents that will register a clock handler and return the handler to the parent
27*/
29{
30public:
31
32 /**
33 Constructor parameters are: parent, clock frequency, clock_index
34 */
36
37 ClockSubComponentAPI(ComponentId_t id) :
38 SST::SubComponent(id)
39 {}
40
41 ClockSubComponentAPI() = default;
42 ~ClockSubComponentAPI() = default;
43
44 /**
45 Return registered clock handler
46 */
47 Clock::HandlerBase* getClockHandler() { return handler_; }
48
49 void serialize_order(SST::Core::Serialization::serializer& ser) override;
50 ImplementSerializable(ClockSubComponentAPI);
51
52protected:
53 // Handler that was registered
54 Clock::HandlerBase* handler_ = nullptr;
55};
56
57class ClockSubComponent : public ClockSubComponentAPI
58{
59public:
60 SST_ELI_REGISTER_SUBCOMPONENT(
61 ClockSubComponent,
62 "coreTestElement",
63 "ClockSubComponent",
64 SST_ELI_ELEMENT_VERSION(1,0,0),
65 "SubComponent which registers an ordered clock that can be returned to the parent",
67 )
68
69 SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS(
70 {"anon_slot", "Slot for anonymous subcomponent", "SST::CoreTestClockerComponent::ClockSubComponentAPI" },
71 {"user_slot", "Slot for user subcomponent", "SST::CoreTestClockerComponent::ClockSubComponentAPI" }
72 )
73
74 ClockSubComponent(ComponentId_t id, Params& p, coreTestClockerComponent* comp, TimeConverter period, int clock);
75 ClockSubComponent() = default;
76 ~ClockSubComponent() = default;
77
78 bool clock_handler(Cycle_t cycle, int clock);
79
80 void serialize_order(SST::Core::Serialization::serializer& ser) override;
81 ImplementSerializable(ClockSubComponent);
82
83private:
84 coreTestClockerComponent* comp_ = nullptr;
85};
86
87class coreTestClockerComponent : public SST::Component
88{
89public:
90 // REGISTER THIS COMPONENT INTO THE ELEMENT LIBRARY
91 SST_ELI_REGISTER_COMPONENT(
92 coreTestClockerComponent,
93 "coreTestElement",
94 "coreTestClockerComponent",
95 SST_ELI_ELEMENT_VERSION(1,0,0),
96 "Clock Benchmark Component",
97 COMPONENT_CATEGORY_UNCATEGORIZED
98 )
99
100 // Optional since there is nothing to document
101 SST_ELI_DOCUMENT_PARAMS(
102 )
103
104 // Optional since there is nothing to document
105 SST_ELI_DOCUMENT_STATISTICS(
106 )
107
108 SST_ELI_DOCUMENT_PORTS(
109 {"left", "Left port", { "" } },
110 {"right", "Right port", { "" } },
111 )
112
113 // Optional since there is nothing to document
114 SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS(
115 )
116
117 coreTestClockerComponent(SST::ComponentId_t id, SST::Params& params);
118
119 // setup() is the only untimed stage used
120 void setup() override;
121
122 void serialize_order(SST::Core::Serialization::serializer& ser) override;
123 ImplementSerializable(coreTestClockerComponent);
124
125private:
126 coreTestClockerComponent() = default; // for serialization only
127 ~coreTestClockerComponent() = default;
128 coreTestClockerComponent(const coreTestClockerComponent&) = delete; // do not implement
129 coreTestClockerComponent& operator=(const coreTestClockerComponent&) = delete; // do not implement
130
131 // Variables to control the simulation
132 static constexpr int total_count = 3;
133 // NOTE: "5ns" is also passed as a string literal to registerClock() in the constructor; keep the two in sync
134 inline static const std::string master_period = "5ns";
135 inline static const std::string test_period = "1ns";
136
137 TimeConverter test_tc;
138
139 // My id is 0 if left_ == nullptr, otherwise, I get an event on my left port and get my id from there, then
140 // increment it and send it on my right port, if I have one.
141 int id_ = -1;
142 int inst_count_ = 0;
143 bool done_ = false;
144
145 Link* left_ = nullptr;
146 Link* right_ = nullptr;
147
148 void handle_left(Event* ev);
149
150 /*
151 Handler for the "master" clock. This will read the instructions and send an event on a self link to execute the
152 instruction. This is done because we can't guarantee the order of execution for the master and test clocks.
153 */
154 bool master_handler(Cycle_t cycle);
155
156 /*
157 Self link to send instructions on
158 */
159 Link* inst_link_;
160
161 /*
162 Handler for the instruction self link
163 */
164 void inst_handler(Event* ev);
165
166public:
167 /**
168 Handler for the "test" clocks. Needs to be public so that subcomponents can call it.
169 */
170 bool test_handler(Cycle_t cycle, int clock_index);
171
172 /**
173 Handler function for ordered clocks
174 */
175 bool test_ordered_handler(Cycle_t cycle, int clock_index);
176
177private:
178 /*
179 There are multiple clocks to test out the various clock APIs in the core:
180
181 Master clock:
182 Period: 50ns
183 - This clock will follow a schedule and start/stop all the other clocks in the simulation
184
185 ** Clocks using the old API
186 Clock 0:
187 Period: 1ns
188 - This clock will count X cycles, then remove itself by returning false from the handler.
189 The master clock will restart it using reregisterClock().
190
191 Clock 1:
192 Period: 1ns
193 - This clock will run until removed from the clock list by the master clock using unregisterClock().
194 The master clock will then restart it later using reregisterClock().
195
196 ** Clocks using the new API
197 Clock 2:
198 Period: 1ns
199 - This clock will count X cycles, then remove itself by returning false from the handler.
200 The master clock will restart it using activate().
201
202 Clock 3:
203 Period: 1ns
204 - This clock will run until removed from the clock list by the master clock using deactivate(),
205 The master clock will then restart it later using activate().
206
207 Clock 4:
208 Period: 1ns
209 - This clock will set ordered_handler_remove_ to true, which causes the ordered clock handlers to remove
210 themselves after completing their operation
211
212 ** Clocks 5-8 will wait to be stopped by the master clock by default. When ordered_handler_remove_ is
213 set to true, they will remove themselves after completing their operation
214
215 Clock 5:
216 Period: 1ns
217 - This clock will initialize ordered_var_test_ to 36
218
219 Clock 6:
220 Period: 1ns
221 - This clock will divide ordered_var_test_ by 2
222 - This clock will be registered by an anonymous subcomponent
223
224 Clock 7:
225 Period: 1ns
226 - This clock will add 6 to ordered_var_test_
227 - This clock will be registered by a user subcomponent
228
229 Clock 8:
230 Period: 1ns
231 - This clock will print ordered_var_test_
232
233 */
234
235 // Struct to hold the data needed to manage the clocks
236 struct ClockInfo
237 {
238 Clock::HandlerBase* handler = nullptr;
239 TimeConverter period;
240 int64_t counter = 0;
241 bool new_style = false;
242
243 void serialize_order(SST::Core::Serialization::serializer& ser)
244 {
245 SST_SER(handler);
246 SST_SER(period);
247 SST_SER(counter);
248 SST_SER(new_style);
249 }
250 };
251
252 // Handler for master clock
253 Clock::HandlerBase* master_ = nullptr;
254
255 // Data for the clocks being tested
256 std::vector<ClockInfo> clocks_;
257
258private:
259
260 // Operations that the master handler can perform
261 enum class Op { nop, start, stop, term };
262
263 int ordered_var_test_ = -1;
264 bool ordered_handler_remove_ = false;
265
266 struct OpBundle
267 {
268 Op op = Op::nop;
269 int clock = -1;
270 };
271
272 // Everyone does the same program, so make it static
273 inline static const std::vector<std::vector<OpBundle>> instructions = {
274 { { Op::start, 1 }, { Op::start, 5 }, { Op::start, 6 }, { Op::start, 7 }, { Op::start, 8 } },
275 { { Op::start, 0 }, { Op::stop, 6 } }, { { Op::start, 3 }, { Op::stop, 7 } },
276 { { Op::stop, 1 }, { Op::start, 6 } },
277 { { Op::start, 2 }, { Op::start, 4 } }, // causes ordered clock handlers to remove themselves
278 { { Op::stop, 3 }, { Op::start, 5 }, { Op::start, 6 }, { Op::start, 8 } },
279 { { Op::start, 1 }, { Op::start, 6 }, { Op::start, 5 }, { Op::start, 8 }, { Op::start, 7 } },
280 { { Op::start, 0 } }, { { Op::start, 3 } }, { { Op::stop, 1 } }, { { Op::start, 2 } }, { { Op::stop, 3 } },
281 { { Op::term, -1 } }
282 };
283
284 using OpEvent = BasicEvent<OpBundle>;
285 using IntEvent = BasicEvent<int>;
286};
287
288} // namespace SST::CoreTestClockerComponent
289
290#endif // SST_CORE_CORETEST_CLOCKERCOMPONENT_H
Basic Event that can hold on data item.
Definition event.h:296
Base classes for clock handlers.
Definition clock.h:146
Main component object for the simulation.
Definition component.h:32
API for SubComponents that will register a clock handler and return the handler to the parent.
Definition coreTest_ClockerComponent.h:29
ClockSubComponentAPI(ComponentId_t id)
Constructor parameters are: parent, clock frequency, clock_index.
Definition coreTest_ClockerComponent.h:37
Clock::HandlerBase * getClockHandler()
Return registered clock handler.
Definition coreTest_ClockerComponent.h:47
Definition coreTest_ClockerComponent.h:88
bool test_ordered_handler(Cycle_t cycle, int clock_index)
Handler function for ordered clocks.
Definition coreTest_ClockerComponent.cc:270
SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS() coreTestClockerComponent(SST void setup() override
Called after all components have been constructed and initialization has completed,...
Definition coreTest_ClockerComponent.cc:171
bool test_handler(Cycle_t cycle, int clock_index)
Handler for the "test" clocks.
Definition coreTest_ClockerComponent.cc:246
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition serializer.h:43
Base class for Events - Items sent across links to communicate between components.
Definition event.h:41
Parameter store.
Definition params.h:65
SubComponent is a class loadable through the factory which allows dynamic functionality to be added t...
Definition subcomponent.h:29
A class to convert between a component's view of time and the core's view of time.
Definition timeConverter.h:31