7#include "ExampleSimulation.hpp"
9#include "CPUFactory.hpp"
12#include "sparta/utils/TimeManager.hpp"
15#include "sparta/trigger/ContextCounterTrigger.hpp"
25#include "Dispatch.hpp"
29#include "FlushManager.hpp"
30#include "Preloader.hpp"
31#include "CustomHistogramStats.hpp"
45 "baz", 0,
"Example parameter set to reproduce bug"))
50 uint32_t read()
const {
51 return int_param_->getValue();
55 std::unique_ptr<Parameter<uint32_t>> int_param_;
63 const std::string & desc) :
64 TreeNode(parent,
"baz_node",
"BazGroup", 0, desc)
71 <<
"' has parameter 'baz' with a value set to "
72 << baz_->read() << std::endl;
75 std::cout <<
"That's the ticket: "
76 << ext->getParameters()->getParameterValueAs<std::string>(
"ticket_") << std::endl;
81 std::unique_ptr<IntParameterSet> baz_;
86template <
typename DataT>
88 const std::string & param_name,
89 const DataT & expected_value)
95 if (actual_value != expected_value) {
97 <<
"\tParameter name: " << param_name
98 <<
"\nParameter value (actual): " << actual_value
99 <<
"\nParameter value (expected): " << expected_value;
103template <
typename DataT>
105 const std::string & param_name,
106 const std::set<DataT> & expected_values)
109 for (
const auto & expected : expected_values) {
112 validateParameter<DataT>(params, param_name, expected);
121 "encountered for '") << param_name <<
"'";
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.";
143 std::unique_ptr<sparta::Parameter<double>> degrees_;
148 virtual void postCreate()
override {
151 "degrees_", 360.0,
"Number of degrees in a circle", ps));
155double calculateAverageOfInternalCounters(
156 const std::vector<const sparta::CounterBase*> & counters)
159 for (
const auto & ctr : counters) {
162 return agg / counters.size();
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)
186 controller_.reset(
new ExampleSimulator::ExampleController(
this));
193 sparta::trigger::ContextCounterTrigger::registerContextCounterCalcFunction(
194 "avg", &calculateAverageOfInternalCounters);
197void ExampleSimulator::registerStatCalculationFcns_()
215ExampleSimulator::~ExampleSimulator()
218 if (on_triggered_notifier_registered_) {
219 getRoot()->DEREGISTER_FOR_NOTIFICATION(
220 onTriggered_, std::string,
"sparta_expression_trigger_fired");
226 auto sparta_res_factory = getResourceSet()->getResourceFactory(
"cpu");
231void ExampleSimulator::buildTree_()
235 registerStatCalculationFcns_();
237 auto cpu_factory = getCPUFactory_();
240 cpu_factory->setTopology(cpu_topology_, num_cores_);
252 cpu_factory->buildTree(
getRoot());
256 std::cout <<
"Registered factories: \n";
257 for(
const auto& f : getCPUFactory_()->getResourceNames()){
258 std::cout <<
"\t" << f << std::endl;
263 for(uint32_t i = 0; i < num_cores_; ++i){
269 if (extensions !=
nullptr) {
272 validateParameter<std::string>(*dispatch_prms,
"when_",
"buildTree_");
273 validateParameter<std::string>(*dispatch_prms,
"why_",
"checkAvailability");
280 if (extensions !=
nullptr) {
283 validateParameter<std::string>(*dispatch_prms,
"edges_",
"4");
292 if (extensions !=
nullptr) {
296 validateParameter<std::string>(*alu0_prms,
"color_",
"black");
297 validateParameter<std::string>(*alu0_prms,
"shape_",
"diamond");
302 if (extensions !=
nullptr) {
306 validateParameter<std::string>(*alu1_prms,
"color_",
"green");
307 validateParameter<std::string>(*alu1_prms,
"shape_",
"circle");
319 if (extensions !=
nullptr) {
323 validateParameter<std::string>(*fpu_prms,
"color_",
"green");
324 validateParameter<std::string>(*fpu_prms,
"shape_",
"round");
325 validateParameter<double> (*fpu_prms,
"degrees_", 360.0);
329 validateParameter<std::string>(*fpu_prms,
"edges_",
"0");
334 circle_subclass->doSomethingElse();
359 dispatch,
"Dummy node under top.cpu.core0.dispatch (to reproduce a SPARTA bug)"));
362 fpu,
"Dummy node under top.cpu.core0.fpu (to reproduce a SPARTA bug)"));
365void ExampleSimulator::configureTree_()
367 validateTreeNodeExtensions_();
375 dispatch_baz_->readParams();
376 fpu_baz_->readParams();
383 if(instruction_limit_ != 0){
388 this->
getRoot()->getSearchScope()->getChild(
"top.cpu.core0.rob"),
389 "testing_notif_channel",
390 "Notification channel for testing purposes only",
391 "testing_notif_channel"));
394 getRoot()->getSearchScope()->getChild(
"top.cpu.core0.rob"),
396 "Notification channel for testing report toggling on/off (statistics profiling)",
401 "all_threads_warmup_instruction_count_retired_re4",
402 "Legacy notificiation channel for testing purposes only",
403 "all_threads_warmup_instruction_count_retired_re4"));
405 getRoot()->REGISTER_FOR_NOTIFICATION(
406 onTriggered_, std::string,
"sparta_expression_trigger_fired");
407 on_triggered_notifier_registered_ =
true;
410void ExampleSimulator::bindTree_()
417 auto cpu_factory = getCPUFactory_();
418 cpu_factory->bindTree(
getRoot());
420 sparta::SpartaHandler cb = sparta::SpartaHandler::from_member<
422 this,
"ExampleSimulator::postRandomNumber_");
424 random_number_trigger_.reset(
new sparta::trigger::ExpressionCounterTrigger(
425 "RandomNumber", cb,
"cpu.core0.rob.stats.total_number_retired 7500",
false, this->
getRoot()));
427 toggle_notif_trigger_.reset(
new sparta::trigger::ExpressionTimeTrigger(
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);
441 num_cores_still_warming_up_ = num_cores_;
442 core_warmup_listeners_.reserve(num_cores_);
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",
449 gen_expression(core_idx),
455void ExampleSimulator::onLegacyWarmupNotification_()
458 --num_cores_still_warming_up_;
459 if (num_cores_still_warming_up_ == 0) {
460 legacy_warmup_report_starter_->postNotification(1);
464const sparta::CounterBase* ExampleSimulator::findSemanticCounter_(CounterSemantic sem)
const {
474void ExampleSimulator::postRandomNumber_()
476 const size_t random = rand() % 25;
477 testing_notification_source_->postNotification(random);
478 random_number_trigger_->reschedule();
481void ExampleSimulator::postToToggleTrigger_()
483 typedef std::pair<uint64_t,uint64_t> ValueCount;
484 static std::queue<ValueCount> values;
486 if (values.empty()) {
493 ValueCount tmp = values.front();
497 if (values.front().second == 0) {
499 ValueCount tmp = values.front();
502 --values.front().second;
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();
511void ExampleSimulator::onTriggered_(
const std::string & msg)
513 std::cout <<
" [trigger] " << msg << std::endl;
516void ExampleSimulator::validateTreeNodeExtensions_()
520 if (core_tn ==
nullptr) {
524 if (cat_base ==
nullptr) {
529 validateParameter<std::string>(*cat_prms,
"name_",
"Tom");
533 validateParameter<std::string>(*cat_prms,
"language_", {
"meow",
"grrr"});
537 if (mouse_base ==
nullptr) {
542 validateParameter<std::string>(*mouse_prms,
"name_",
"Jerry");
543 validateParameter<std::string>(*mouse_prms,
"language_",
"squeak");
547 if (fpu_tn ==
nullptr) {
551 if (circle_base ==
nullptr) {
557 validateParameter<std::string>(*circle_prms,
"color_",
"green");
558 validateParameter<std::string>(*circle_prms,
"shape_",
"round");
561 validateParameter<double>(*circle_prms,
"degrees_", 360.0);
566 circle_subclass->doSomethingElse();
570 if (top_node ==
nullptr) {
574 if (top_extensions ==
nullptr) {
578 validateParameter<std::string>(*top_prms,
"color_",
"red");
585 "call to TreeNode::getExtension()");
592 circle_prms = circle_base_by_default->getParameters();
594 validateParameter<std::string>(*circle_prms,
"color_",
"green");
595 validateParameter<std::string>(*circle_prms,
"shape_",
"round");
596 validateParameter<double>(*circle_prms,
"degrees_", 360.0);
601 if (circle_prms->getNumParameters() > 3) {
602 validateParameter<std::string>(*circle_prms,
"edges_",
"0");
613 validateParameter<std::string>(*baz_prms,
"ticket_",
"663");
618ExampleSimulator::ExampleController::ExampleController(
620 sparta::app::Simulation::SimulationController(sim)
622 sparta::app::Simulation::SimulationController::addNamedCallback_(
625 sparta::app::Simulation::SimulationController::addNamedCallback_(
631 std::cout <<
" [control] Controller PAUSE method has been called for simulation '"
637 std::cout <<
" [control] Controller RESUME method has been called for simulation '"
643 std::cout <<
" [control] Controller TERMINATE method has been called for simulation '"
648void ExampleSimulator::ExampleController::customEatCallback_()
650 std::cout <<
" [control] Controller CUSTOM method has been called ('eat')" << std::endl;
653void ExampleSimulator::ExampleController::customSleepCallback_()
655 std::cout <<
" [control] Controller CUSTOM method has been called ('sleep')" << std::endl;
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.
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.
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
std::string getLocation() const override final
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
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.