The Sparta Modeling Framework
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ExampleSimulation.cpp
1// <Simulation.cpp> -*- C++ -*-
2
3
4#include <iostream>
5
6
7#include "ExampleSimulation.hpp"
8#include "Core.hpp"
9#include "CPUFactory.hpp"
10
12#include "sparta/utils/TimeManager.hpp"
15#include "sparta/trigger/ContextCounterTrigger.hpp"
21
22#include "Fetch.hpp"
23#include "Decode.hpp"
24#include "Rename.hpp"
25#include "Dispatch.hpp"
26#include "Execute.hpp"
27#include "LSU.hpp"
28#include "ROB.hpp"
29#include "FlushManager.hpp"
30#include "Preloader.hpp"
31#include "CustomHistogramStats.hpp"
32
33// UPDATE
34#include "BIU.hpp"
35#include "MSS.hpp"
36
37namespace sparta {
38
39 // Example parameter set used to reproduce write-final-config
41 public:
42 IntParameterSet(TreeNode * parent) :
43 ParameterSet(parent),
44 int_param_(new Parameter<uint32_t>(
45 "baz", 0, "Example parameter set to reproduce bug"))
46 {
47 addParameter_(int_param_.get());
48 }
49
50 uint32_t read() const {
51 return int_param_->getValue();
52 }
53
54 private:
55 std::unique_ptr<Parameter<uint32_t>> int_param_;
56 };
57
58 // Dummy node class used together with IntParameterSet to
59 // reproduce write-final-config bug
60 class Baz : public TreeNode {
61 public:
62 Baz(TreeNode* parent,
63 const std::string & desc) :
64 TreeNode(parent, "baz_node", "BazGroup", 0, desc)
65 {
66 baz_.reset(new IntParameterSet(this));
67 }
68
69 void readParams() {
70 std::cout << " Node '" << getLocation()
71 << "' has parameter 'baz' with a value set to "
72 << baz_->read() << std::endl;
73 auto ext = getExtension("baz_ext");
74 if(ext) {
75 std::cout << "That's the ticket: "
76 << ext->getParameters()->getParameterValueAs<std::string>("ticket_") << std::endl;
77 }
78 }
79
80 private:
81 std::unique_ptr<IntParameterSet> baz_;
82 };
83
84}
85
86template <typename DataT>
87void validateParameter(const sparta::ParameterSet & params,
88 const std::string & param_name,
89 const DataT & expected_value)
90{
91 if (!params.hasParameter(param_name)) {
92 return;
93 }
94 const DataT actual_value = params.getParameterValueAs<DataT>(param_name);
95 if (actual_value != expected_value) {
96 throw sparta::SpartaException("Invalid extension parameter encountered:\n")
97 << "\tParameter name: " << param_name
98 << "\nParameter value (actual): " << actual_value
99 << "\nParameter value (expected): " << expected_value;
100 }
101}
102
103template <typename DataT>
104void validateParameter(const sparta::ParameterSet & params,
105 const std::string & param_name,
106 const std::set<DataT> & expected_values)
107{
108 bool found = false;
109 for (const auto & expected : expected_values) {
110 try {
111 found = false;
112 validateParameter<DataT>(params, param_name, expected);
113 found = true;
114 break;
115 } catch (...) {
116 }
117 }
118
119 if (!found) {
120 throw sparta::SpartaException("Invalid extension parameter "
121 "encountered for '") << param_name << "'";
122 }
123}
124
126{
127public:
129 virtual ~CircleExtensions() {}
130
131 void doSomethingElse() const {
132 std::cout << "Invoking a method that is unknown to the sparta::TreeNode object, "
133 "even though 'this' object was created by, and currently owned by, "
134 "a specific tree node.";
135 }
136
137private:
138
139 // Note: this parameter is NOT in the yaml config file,
140 // but subclasses can provide any parameter type supported
141 // by sparta::Parameter<T> which may be too complicated to
142 // clearly describe using simple yaml syntax
143 std::unique_ptr<sparta::Parameter<double>> degrees_;
144
145 // The base class will clobber together whatever parameter values it
146 // found in the yaml file, and give us a chance to add custom parameters
147 // to the same set
148 virtual void postCreate() override {
149 sparta::ParameterSet * ps = getParameters();
150 degrees_.reset(new sparta::Parameter<double>(
151 "degrees_", 360.0, "Number of degrees in a circle", ps));
152 }
153};
154
155double calculateAverageOfInternalCounters(
156 const std::vector<const sparta::CounterBase*> & counters)
157{
158 double agg = 0;
159 for (const auto & ctr : counters) {
160 agg += ctr->get();
161 }
162 return agg / counters.size();
163}
164
165ExampleSimulator::ExampleSimulator(const std::string& topology,
166 sparta::Scheduler & scheduler,
167 uint32_t num_cores,
168 uint64_t instruction_limit,
169 bool show_factories) :
170 sparta::app::Simulation("sparta_core_example", &scheduler),
171 cpu_topology_(topology),
172 num_cores_(num_cores),
173 instruction_limit_(instruction_limit),
174 show_factories_(show_factories)
175{
176 // Set up the CPU Resource Factory to be available through ResourceTreeNode
178
179 // Set up all node extension factories to be available during the simulation
180 // - This is only needed for parameter sets that also want to add some methods
181 // to their tree node extension, and/or for those that want to extend node
182 // parameter sets with more complicated sparta::Parameter<T> data types
183 addTreeNodeExtensionFactory_("circle", [](){return new CircleExtensions;});
184
185 // Initialize example simulation controller
186 controller_.reset(new ExampleSimulator::ExampleController(this));
188
189 // Register a custom calculation method for 'combining' a context counter's
190 // internal counters into one number. In this example simulator, let's just
191 // use an averaging function called "avg" which we can then invoke from report
192 // definition YAML files.
193 sparta::trigger::ContextCounterTrigger::registerContextCounterCalcFunction(
194 "avg", &calculateAverageOfInternalCounters);
195}
196
197void ExampleSimulator::registerStatCalculationFcns_()
198{
199 REGISTER_HISTOGRAM_STAT_CALC_FCN(CycleHistogramTreeNode, stdev_x3);
200 REGISTER_HISTOGRAM_STAT_CALC_FCN(CycleHistogramTreeNode, fraction_coverage_greaterThan2StdDev);
201 REGISTER_HISTOGRAM_STAT_CALC_FCN(CycleHistogramTreeNode, fraction_coverage_mean_p_StdDev_mean_p_2StdDev);
202 REGISTER_HISTOGRAM_STAT_CALC_FCN(CycleHistogramTreeNode, fraction_coverage_mean_mean_p_StdDev);
203 REGISTER_HISTOGRAM_STAT_CALC_FCN(CycleHistogramTreeNode, fraction_coverage_mean_m_StdDev_mean);
204 REGISTER_HISTOGRAM_STAT_CALC_FCN(CycleHistogramTreeNode, fraction_coverage_mean_m_2StdDev_mean_m_StdDev);
205 REGISTER_HISTOGRAM_STAT_CALC_FCN(CycleHistogramTreeNode, fraction_coverage_lesserThan2StdDev);
206 REGISTER_HISTOGRAM_STAT_CALC_FCN(HistogramTreeNode, stdev_x3_h);
207 REGISTER_HISTOGRAM_STAT_CALC_FCN(HistogramTreeNode, fraction_coverage_greaterThan2StdDev_h);
208 REGISTER_HISTOGRAM_STAT_CALC_FCN(HistogramTreeNode, fraction_coverage_mean_p_StdDev_mean_p_2StdDev_h);
209 REGISTER_HISTOGRAM_STAT_CALC_FCN(HistogramTreeNode, fraction_coverage_mean_mean_p_StdDev_h);
210 REGISTER_HISTOGRAM_STAT_CALC_FCN(HistogramTreeNode, fraction_coverage_mean_m_StdDev_mean_h);
211 REGISTER_HISTOGRAM_STAT_CALC_FCN(HistogramTreeNode, fraction_coverage_mean_m_2StdDev_mean_m_StdDev_h);
212 REGISTER_HISTOGRAM_STAT_CALC_FCN(HistogramTreeNode, fraction_coverage_lesserThan2StdDev_h);
213}
214
215ExampleSimulator::~ExampleSimulator()
216{
217 getRoot()->enterTeardown(); // Allow deletion of nodes without error now
218 if (on_triggered_notifier_registered_) {
219 getRoot()->DEREGISTER_FOR_NOTIFICATION(
220 onTriggered_, std::string, "sparta_expression_trigger_fired");
221 }
222}
223
225auto ExampleSimulator::getCPUFactory_() -> core_example::CPUFactory*{
226 auto sparta_res_factory = getResourceSet()->getResourceFactory("cpu");
227 auto cpu_factory = dynamic_cast<core_example::CPUFactory*>(sparta_res_factory);
228 return cpu_factory;
229}
230
231void ExampleSimulator::buildTree_()
232{
233 // TREE_BUILDING Phase. See sparta::PhasedObject::TreePhase
234 // Register all the custom stat calculation functions with (cycle)histogram nodes
235 registerStatCalculationFcns_();
236
237 auto cpu_factory = getCPUFactory_();
238
239 // Set the cpu topology that will be built
240 cpu_factory->setTopology(cpu_topology_, num_cores_);
241
242 // Create a single CPU
244 "cpu",
247 "CPU Node",
248 cpu_factory);
249 to_delete_.emplace_back(cpu_tn);
250
251 // Tell the factory to build the resources now
252 cpu_factory->buildTree(getRoot());
253
254 // Print the registered factories
255 if(show_factories_){
256 std::cout << "Registered factories: \n";
257 for(const auto& f : getCPUFactory_()->getResourceNames()){
258 std::cout << "\t" << f << std::endl;
259 }
260 }
261
262 // Validate tree node extensions during tree building
263 for(uint32_t i = 0; i < num_cores_; ++i){
264 sparta::TreeNode * dispatch = getRoot()->getChild("cpu.core0.dispatch", false);
265 if (dispatch) {
266 sparta::TreeNode::ExtensionsBase * extensions = dispatch->getExtension("user_data");
267
268 // If present, validate the parameter values as given in the extension / configuration file
269 if (extensions != nullptr) {
270 const sparta::ParameterSet * dispatch_prms = extensions->getParameters();
271 sparta_assert(dispatch_prms != nullptr);
272 validateParameter<std::string>(*dispatch_prms, "when_", "buildTree_");
273 validateParameter<std::string>(*dispatch_prms, "why_", "checkAvailability");
274 }
275
276 // There might be an extension given in --extension-file that is not found
277 // at all in any --config-file given at the command prompt. Verify that if
278 // present, the value is as expected.
279 extensions = dispatch->getExtension("square");
280 if (extensions != nullptr) {
281 const sparta::ParameterSet * dispatch_prms = extensions->getParameters();
282 sparta_assert(dispatch_prms != nullptr);
283 validateParameter<std::string>(*dispatch_prms, "edges_", "4");
284 }
285 }
286
287 // See if there are any extensions for the alu0/alu1 nodes
288 sparta::TreeNode * alu0 = getRoot()->getChild("cpu.core0.alu0");
289 sparta::TreeNode * alu1 = getRoot()->getChild("cpu.core0.alu1");
290 if (alu0) {
291 sparta::TreeNode::ExtensionsBase * extensions = alu0->getExtension("difficulty");
292 if (extensions != nullptr) {
293 const sparta::ParameterSet * alu0_prms = extensions->getParameters();
294 sparta_assert(alu0_prms != nullptr);
295
296 validateParameter<std::string>(*alu0_prms, "color_", "black");
297 validateParameter<std::string>(*alu0_prms, "shape_", "diamond");
298 }
299 }
300 if (alu1) {
301 sparta::TreeNode::ExtensionsBase * extensions = alu1->getExtension("difficulty");
302 if (extensions != nullptr) {
303 const sparta::ParameterSet * alu1_prms = extensions->getParameters();
304 sparta_assert(alu1_prms != nullptr);
305
306 validateParameter<std::string>(*alu1_prms, "color_", "green");
307 validateParameter<std::string>(*alu1_prms, "shape_", "circle");
308 }
309 }
310
311 // Once again, ask for a named extension for a tree node that was just created.
312 // The difference here is that the 'circle' extension also has a factory associated
313 // with it.
314 sparta::TreeNode * fpu = getRoot()->getChild("cpu.core0.fpu", false);
315 if (fpu) {
316 sparta::TreeNode::ExtensionsBase * extensions = fpu->getExtension("circle");
317
318 // If present, validate the parameter values as given in the extension / configuration file
319 if (extensions != nullptr) {
320 const sparta::ParameterSet * fpu_prms = extensions->getParameters();
321 sparta_assert(fpu_prms != nullptr);
322
323 validateParameter<std::string>(*fpu_prms, "color_", "green");
324 validateParameter<std::string>(*fpu_prms, "shape_", "round");
325 validateParameter<double> (*fpu_prms, "degrees_", 360.0);
326
327 // While most of the 'circle' extensions are given in --config-file options,
328 // there might be more parameters added in with --extension-file, so let's check
329 validateParameter<std::string>(*fpu_prms, "edges_", "0");
330
331 // We know the subclass type, so we should be able to safely dynamic cast
332 // to that type and call methods on it
333 const CircleExtensions * circle_subclass = dynamic_cast<const CircleExtensions*>(extensions);
334 circle_subclass->doSomethingElse();
335 }
336 }
337 }
338
339 // Attach two tree nodes to get the following:
340 // top
341 // core0
342 // dispatch
343 // baz_node
344 // params
345 // baz
346 // fpu
347 // baz_node
348 // params
349 // baz
350 //
351 // This is needed to reproduce a write-final-config bug where an arch file
352 // specifies 'top.core0.*.baz_node.params.baz: 300' and the ConfigEmitterYAML
353 // ends up throwing an exception due to the '*' which tripped up the tree node
354 // extensions code.
355 auto dispatch = getRoot()->getChild("cpu.core0.dispatch");
356 auto fpu = getRoot()->getChild("cpu.core0.fpu");
357
358 dispatch_baz_.reset(new sparta::Baz(
359 dispatch, "Dummy node under top.cpu.core0.dispatch (to reproduce a SPARTA bug)"));
360
361 fpu_baz_.reset(new sparta::Baz(
362 fpu, "Dummy node under top.cpu.core0.fpu (to reproduce a SPARTA bug)"));
363}
364
365void ExampleSimulator::configureTree_()
366{
367 validateTreeNodeExtensions_();
368
369 // In TREE_CONFIGURING phase
370 // Configuration from command line is already applied
371
372 // Read these parameter values to avoid 'unread unbound parameter' exceptions:
373 // top.cpu.core0.dispatch.baz_node.params.baz
374 // top.cpu.core0.fpu.baz_node.params.baz
375 dispatch_baz_->readParams();
376 fpu_baz_->readParams();
377
378 sparta::ParameterBase* max_instrs =
379 getRoot()->getChildAs<sparta::ParameterBase>("cpu.core0.rob.params.num_insts_to_retire");
380
381 // Safely assign as string for now in case parameter type changes.
382 // Direct integer assignment without knowing parameter type is not yet available through C++ API
383 if(instruction_limit_ != 0){
384 max_instrs->setValueFromString(sparta::utils::uint64_to_str(instruction_limit_));
385 }
386
387 testing_notification_source_.reset(new sparta::NotificationSource<uint64_t>(
388 this->getRoot()->getSearchScope()->getChild("top.cpu.core0.rob"),
389 "testing_notif_channel",
390 "Notification channel for testing purposes only",
391 "testing_notif_channel"));
392
393 toggle_trigger_notification_source_.reset(new sparta::NotificationSource<uint64_t>(
394 getRoot()->getSearchScope()->getChild("top.cpu.core0.rob"),
395 "stats_profiler",
396 "Notification channel for testing report toggling on/off (statistics profiling)",
397 "stats_profiler"));
398
399 legacy_warmup_report_starter_.reset(new sparta::NotificationSource<uint64_t>(
400 getRoot(),
401 "all_threads_warmup_instruction_count_retired_re4",
402 "Legacy notificiation channel for testing purposes only",
403 "all_threads_warmup_instruction_count_retired_re4"));
404
405 getRoot()->REGISTER_FOR_NOTIFICATION(
406 onTriggered_, std::string, "sparta_expression_trigger_fired");
407 on_triggered_notifier_registered_ = true;
408}
409
410void ExampleSimulator::bindTree_()
411{
412 // In TREE_FINALIZED phase
413 // Tree is finalized. Taps placed. No new nodes at this point
414 // Bind appropriate ports
415
416 //Tell the factory to bind all units
417 auto cpu_factory = getCPUFactory_();
418 cpu_factory->bindTree(getRoot());
419
420 sparta::SpartaHandler cb = sparta::SpartaHandler::from_member<
421 ExampleSimulator, &ExampleSimulator::postRandomNumber_>(
422 this, "ExampleSimulator::postRandomNumber_");
423
424 random_number_trigger_.reset(new sparta::trigger::ExpressionCounterTrigger(
425 "RandomNumber", cb, "cpu.core0.rob.stats.total_number_retired 7500", false, this->getRoot()));
426
427 toggle_notif_trigger_.reset(new sparta::trigger::ExpressionTimeTrigger(
428 "ToggleNotif",
429 CREATE_SPARTA_HANDLER(ExampleSimulator, postToToggleTrigger_),
430 "1 ns",
431 getRoot()));
432
433 static const uint32_t warmup_multiplier = 1000;
434 auto gen_expression = [](const uint32_t core_idx) {
435 std::ostringstream oss;
436 oss << "cpu.core" << core_idx << ".rob.stats.total_number_retired >= "
437 << ((core_idx+1) * warmup_multiplier);
438 return oss.str();
439 };
440
441 num_cores_still_warming_up_ = num_cores_;
442 core_warmup_listeners_.reserve(num_cores_);
443
444 for (uint32_t core_idx = 0; core_idx < num_cores_; ++core_idx) {
445 core_warmup_listeners_.emplace_back(
446 new sparta::trigger::ExpressionTrigger(
447 "LegacyWarmupNotifications",
448 CREATE_SPARTA_HANDLER(ExampleSimulator, onLegacyWarmupNotification_),
449 gen_expression(core_idx),
450 getRoot(),
451 nullptr));
452 }
453}
454
455void ExampleSimulator::onLegacyWarmupNotification_()
456{
457 sparta_assert(num_cores_still_warming_up_ > 0);
458 --num_cores_still_warming_up_;
459 if (num_cores_still_warming_up_ == 0) {
460 legacy_warmup_report_starter_->postNotification(1);
461 }
462}
463
464const sparta::CounterBase* ExampleSimulator::findSemanticCounter_(CounterSemantic sem) const {
465 switch(sem){
467 return getRoot()->getChildAs<const sparta::CounterBase>("cpu.core0.rob.stats.total_number_retired");
468 break;
469 default:
470 return nullptr;
471 }
472}
473
474void ExampleSimulator::postRandomNumber_()
475{
476 const size_t random = rand() % 25;
477 testing_notification_source_->postNotification(random);
478 random_number_trigger_->reschedule();
479}
480
481void ExampleSimulator::postToToggleTrigger_()
482{
483 typedef std::pair<uint64_t,uint64_t> ValueCount;
484 static std::queue<ValueCount> values;
485
486 if (values.empty()) {
487 values.push({0,15});
488 values.push({1,25});
489 values.push({0,15});
490 values.push({1,25});
491 values.push({0,15});
492
493 ValueCount tmp = values.front();
494 values.push(tmp);
495 }
496
497 if (values.front().second == 0) {
498 values.pop();
499 ValueCount tmp = values.front();
500 values.push(tmp);
501 } else {
502 --values.front().second;
503 }
504
505 const ValueCount & current_value = values.front();
506 const uint64_t value_to_post = current_value.first;
507 toggle_trigger_notification_source_->postNotification(value_to_post);
508 toggle_notif_trigger_->reschedule();
509}
510
511void ExampleSimulator::onTriggered_(const std::string & msg)
512{
513 std::cout << " [trigger] " << msg << std::endl;
514}
515
516void ExampleSimulator::validateTreeNodeExtensions_()
517{
518 // From the yaml file, the 'cat' extension had parameters 'name_' and 'language_'
519 sparta::TreeNode * core_tn = getRoot()->getChild("cpu.core0.lsu");
520 if (core_tn == nullptr) {
521 return;
522 }
523 sparta::TreeNode::ExtensionsBase * cat_base = core_tn->getExtension("cat");
524 if (cat_base == nullptr) {
525 return;
526 }
527 sparta::ParameterSet * cat_prms = cat_base->getParameters();
528
529 validateParameter<std::string>(*cat_prms, "name_", "Tom");
530
531 // The expected "meow" parameter value, given in a --config-file, may have
532 // been overridden in a provided --extension-file
533 validateParameter<std::string>(*cat_prms, "language_", {"meow", "grrr"});
534
535 // Same goes for the 'mouse' extension...
536 sparta::TreeNode::ExtensionsBase * mouse_base = core_tn->getExtension("mouse");
537 if (mouse_base == nullptr) {
538 return;
539 }
540 sparta::ParameterSet * mouse_prms = mouse_base->getParameters();
541
542 validateParameter<std::string>(*mouse_prms, "name_", "Jerry");
543 validateParameter<std::string>(*mouse_prms, "language_", "squeak");
544
545 // Another extension called 'circle' was put on a different tree node...
546 sparta::TreeNode * fpu_tn = getRoot()->getChild("cpu.core0.fpu");
547 if (fpu_tn == nullptr) {
548 return;
549 }
550 sparta::TreeNode::ExtensionsBase * circle_base = fpu_tn->getExtension("circle");
551 if (circle_base == nullptr) {
552 return;
553 }
554 sparta::ParameterSet * circle_prms = circle_base->getParameters();
555
556 // The 'circle' extension had 'color_' and 'shape_' parameters given in the yaml file:
557 validateParameter<std::string>(*circle_prms, "color_", "green");
558 validateParameter<std::string>(*circle_prms, "shape_", "round");
559
560 // That subclass also gave a parameter value not found in the yaml file at all:
561 validateParameter<double>(*circle_prms, "degrees_", 360.0);
562
563 // Further, the 'circle' extension gave a subclass factory for the CircleExtensions class...
564 // so we should be able to dynamic_cast to the known type:
565 const CircleExtensions * circle_subclass = dynamic_cast<const CircleExtensions*>(circle_base);
566 circle_subclass->doSomethingElse();
567
568 // Lastly, verify that there are no issues with putting extensions on the 'top' node
569 sparta::TreeNode * top_node = getRoot();
570 if (top_node == nullptr) {
571 return;
572 }
573 sparta::TreeNode::ExtensionsBase * top_extensions = top_node->getExtension("apple");
574 if (top_extensions == nullptr) {
575 return;
576 }
577 sparta::ParameterSet *top_prms = top_extensions->getParameters();
578 validateParameter<std::string>(*top_prms, "color_", "red");
579
580 // The 'core0.lsu' node has two named extensions, so asking that node for
581 // unqualified extensions (no name specified) should throw
582 try {
583 core_tn->getExtension();
584 throw sparta::SpartaException("Expected an exception to be thrown for unqualified "
585 "call to TreeNode::getExtension()");
586 } catch (...) {
587 }
588
589 // While the 'core0.fpu' node only had one extension, so we should be able to
590 // access it without giving any particular name
591 sparta::TreeNode::ExtensionsBase * circle_base_by_default = fpu_tn->getExtension();
592 circle_prms = circle_base_by_default->getParameters();
593
594 validateParameter<std::string>(*circle_prms, "color_", "green");
595 validateParameter<std::string>(*circle_prms, "shape_", "round");
596 validateParameter<double>(*circle_prms, "degrees_", 360.0);
597
598 // Check to see if additional parameters were added to this tree node's extension
599 // (--config-file and --extension-file options can be given at the same time, and
600 // we should have access to the merged result of both ParameterTree's)
601 if (circle_prms->getNumParameters() > 3) {
602 validateParameter<std::string>(*circle_prms, "edges_", "0");
603 }
604
605 // Verify that we can work with extensions on 'top.core0.dispatch.baz_node', which
606 // was added to this example simulator to reproduce bug
607 sparta::TreeNode * baz_node = getRoot()->getChild("cpu.core0.dispatch.baz_node", false);
608 if (baz_node) {
609 sparta::TreeNode::ExtensionsBase * extensions = baz_node->getExtension("baz_ext");
610 if (extensions) {
611 const sparta::ParameterSet * baz_prms = extensions->getParameters();
612 sparta_assert(baz_prms != nullptr);
613 validateParameter<std::string>(*baz_prms, "ticket_", "663");
614 }
615 }
616}
617
618ExampleSimulator::ExampleController::ExampleController(
619 const sparta::app::Simulation * sim) :
620 sparta::app::Simulation::SimulationController(sim)
621{
622 sparta::app::Simulation::SimulationController::addNamedCallback_(
623 "eat", CREATE_SPARTA_HANDLER(ExampleController, customEatCallback_));
624
625 sparta::app::Simulation::SimulationController::addNamedCallback_(
626 "sleep", CREATE_SPARTA_HANDLER(ExampleController, customSleepCallback_));
627}
628
629void ExampleSimulator::ExampleController::pause_(const sparta::app::Simulation * sim)
630{
631 std::cout << " [control] Controller PAUSE method has been called for simulation '"
632 << sim->getSimName() << "'" << std::endl;
633}
634
635void ExampleSimulator::ExampleController::resume_(const sparta::app::Simulation * sim)
636{
637 std::cout << " [control] Controller RESUME method has been called for simulation '"
638 << sim->getSimName() << "'" << std::endl;
639}
640
641void ExampleSimulator::ExampleController::terminate_(const sparta::app::Simulation * sim)
642{
643 std::cout << " [control] Controller TERMINATE method has been called for simulation '"
644 << sim->getSimName() << "'" << std::endl;
645 const_cast<sparta::Scheduler*>(sim->getScheduler())->stopRunning();
646}
647
648void ExampleSimulator::ExampleController::customEatCallback_()
649{
650 std::cout << " [control] Controller CUSTOM method has been called ('eat')" << std::endl;
651}
652
653void ExampleSimulator::ExampleController::customSleepCallback_()
654{
655 std::cout << " [control] Controller CUSTOM method has been called ('sleep')" << std::endl;
656}
File that defines the Clock class.
CycleHistogram implementation using sparta CycleCounter.
Definition of the CoreModel Fetch unit.
#define REGISTER_HISTOGRAM_STAT_CALC_FCN(histogram_type, fcn_name)
Function Registration Macro for Histogram/CycleHistogram. This macro is called by the users in their ...
Histogram implementation using sparta Counters.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
#define CREATE_SPARTA_HANDLER(clname, meth)
File that defines the SpartaTester class and testing Macros.
Cool string utilities.
Basic Node framework in sparta device tree composite pattern.
ExampleSimulator which builds the model and configures it.
ExampleSimulator(const std::string &topology, sparta::Scheduler &scheduler, uint32_t num_cores=1, uint64_t instruction_limit=0, bool show_factories=false)
Construct ExampleSimulator.
The base class for all Counters.
Helper class used to trivially extend TreeNode parameter sets (but not any additional functionality b...
A TreeNode that generates a specific type of notification which propagates up a tree of TreeNodes (us...
Non-templated base class for generic parameter access and iteration.
void setValueFromString(const std::string &str, bool poke=false)
Attempts to assign a value to this non-vector Parameter from a string.
Generic container of Parameters.
ParameterSet()=delete
Default constructor disabled.
const T getParameterValueAs(const std::string &name) const
Finds a parameter and gets its value as the templated type.
void addParameter_(sparta::ParameterBase *p)
Add a parameter to the parameter set. \temp This will be removed.
bool hasParameter(const std::string &name) const
Determines whether this ParameterSet has the parameter with the given name.
Parameter instance, templated to contain only a specific type.
void addResourceFactory()
Add a resource factory by its template type.
TreeNode subclass representing a node in the device tree which contains a single ResourceFactory and ...
void enterTeardown()
Places this tree into TREE_TEARDOWN phase so that nodes may be deleted without errors.
A class that lets you schedule events now and in the future.
void stopRunning()
Tell the scheduler to stop running.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Base class used to extend TreeNode parameter sets.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
Definition TreeNode.hpp:303
std::string getLocation() const override final
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
Definition TreeNode.hpp:314
TreeNode()=delete
Not default-constructable.
ExtensionsBase * getExtension()
Get an extension without needing to specify any particular type string. If no extensions exist,...
ExtensionsBase * getExtension(const std::string &extension_name)
Get an extension object by type string. Returns nullptr if not found (unrecognized).
const ConstT getChildAs(const std::string &name, bool must_exist=true) const
Retrieves a child that is castable to T with the given dotted path.
TreeNode * getChild(const std::string &name, bool must_exist=true)
Retrieves a child with this dotted path name.
Simulator which builds a sparta DeviceTree.
std::vector< std::unique_ptr< sparta::TreeNode > > to_delete_
Vector of TreeNodes to delete automatically at destruction. Add any nodes allocated to this list to a...
@ CSEM_INSTRUCTIONS
Instruction count semantic (usually core0)
std::shared_ptr< SimulationController > controller_
Custom controller to handle various simulation events.
sparta::RootTreeNode * getRoot() noexcept
Returns the tree root.
void addTreeNodeExtensionFactory_(const std::string &extension_name, std::function< TreeNode::ExtensionsBase *()> creator)
Include an extension factory for this simulation's device tree nodes. They will be given to specific ...
void setSimulationController_(std::shared_ptr< SimulationController > controller)
Set a controller to handle custom simulation events.
sparta::ResourceSet * getResourceSet() noexcept
Returns the resource set for this Simulation.
const std::string & getSimName() const noexcept
Returns this simulator's name.
sparta::Scheduler * getScheduler()
Returns the simulation's scheduler.
Macros for handling exponential backoff.