7#include "ExampleSimulation.hpp"
9#include "CPUFactory.hpp"
12#include "sparta/utils/TimeManager.hpp"
14#include "sparta/simulation/TreeNodeExtensions.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;
76 std::cout <<
"That's the ticket: "
77 << ext->getParameters()->getParameterValueAs<std::string>(
"ticket_") << std::endl;
82 std::unique_ptr<IntParameterSet> baz_;
90 void doSomethingElse()
const {
91 std::cout <<
"Invoking a method that is unknown to the sparta::TreeNode object, "
92 "even though 'this' object was created by, and currently owned by, "
93 "a specific tree node.";
101 std::unique_ptr<sparta::Parameter<double>> degrees_;
106 void postCreate()
override {
109 "degrees_", 360.0,
"Number of degrees in a circle", ps));
116 void postCreate()
override {
119 "value_", 555,
"Dummy value", ps));
122 std::unique_ptr<sparta::Parameter<int>> value_;
125double calculateAverageOfInternalCounters(
126 const std::vector<const sparta::CounterBase*> & counters)
129 for (
const auto & ctr : counters) {
132 return agg / counters.size();
138 uint64_t instruction_limit,
139 bool show_factories) :
140 sparta::app::Simulation(
"sparta_core_example", &scheduler),
141 cpu_topology_(topology),
142 num_cores_(num_cores),
143 instruction_limit_(instruction_limit),
144 show_factories_(show_factories)
157 controller_.reset(
new ExampleSimulator::ExampleController(
this));
164 sparta::trigger::ContextCounterTrigger::registerContextCounterCalcFunction(
165 "avg", &calculateAverageOfInternalCounters);
168void ExampleSimulator::registerStatCalculationFcns_()
186ExampleSimulator::~ExampleSimulator()
189 if (on_triggered_notifier_registered_) {
190 getRoot()->DEREGISTER_FOR_NOTIFICATION(
191 onTriggered_, std::string,
"sparta_expression_trigger_fired");
197 auto sparta_res_factory = getResourceSet()->getResourceFactory(
"cpu");
202void ExampleSimulator::buildTree_()
206 registerStatCalculationFcns_();
208 auto cpu_factory = getCPUFactory_();
211 cpu_factory->setTopology(cpu_topology_, num_cores_);
223 cpu_factory->buildTree(
getRoot());
227 std::cout <<
"Registered factories: \n";
228 for(
const auto& f : getCPUFactory_()->getResourceNames()){
229 std::cout <<
"\t" << f << std::endl;
234 for(uint32_t i = 0; i < num_cores_; ++i){
235 const std::string dispatch_loc =
"cpu.core" + std::to_string(i) +
".dispatch";
236 const std::string alu0_loc =
"cpu.core" + std::to_string(i) +
".alu0";
237 const std::string alu1_loc =
"cpu.core" + std::to_string(i) +
".alu1";
238 const std::string fpu_loc =
"cpu.core" + std::to_string(i) +
".fpu";
241 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(dispatch_loc),
"when_",
"user_data")) {
242 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
243 return val ==
"buildTree_";
244 },
"Parameter 'when_' should be 'buildTree_'");
248 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(dispatch_loc),
"why_",
"user_data")) {
249 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
250 return val ==
"checkAvailability";
251 },
"Parameter 'why_' should be 'checkAvailability'");
255 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(dispatch_loc),
"edges_",
"square")) {
256 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
258 },
"Parameter 'edges_' should be '4'");
262 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(alu0_loc),
"color_",
"difficulty")) {
263 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
264 return val ==
"black";
265 },
"Parameter 'color_' should be 'black'");
269 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(alu0_loc),
"shape_",
"difficulty")) {
270 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
271 return val ==
"diamond";
272 },
"Parameter 'shape_' should be 'diamond'");
276 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(alu1_loc),
"color_",
"difficulty")) {
277 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
278 return val ==
"green";
279 },
"Parameter 'color_' should be 'green'");
283 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(alu1_loc),
"shape_",
"difficulty")) {
284 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
285 return val ==
"circle";
286 },
"Parameter 'shape_' should be 'circle'");
290 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(fpu_loc),
"color_",
"circle")) {
291 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
292 return val ==
"green";
293 },
"Parameter 'color_' should be 'green'");
297 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(fpu_loc),
"shape_",
"circle")) {
298 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
299 return val ==
"round";
300 },
"Parameter 'shape_' should be 'round'");
304 if (
auto prm = getExtensionParameter_<double>(
getRoot()->getChild(fpu_loc),
"degrees_",
"circle")) {
305 prm->addDependentValidationCallback([](
double & val,
const sparta::TreeNode*) ->
bool {
307 },
"Parameter 'degrees_' should be 360.0");
311 if (
auto prm = getExtensionParameter_<std::string>(
getRoot()->getChild(fpu_loc),
"edges_",
"circle")) {
312 prm->addDependentValidationCallback([](std::string & val,
const sparta::TreeNode*) ->
bool {
314 },
"Parameter 'edges_' should be '0'");
318 getExtension_<CircleExtensions>(
getRoot()->getChild(fpu_loc),
"circle")->doSomethingElse();
341 dispatch,
"Dummy node under top.cpu.core0.dispatch (to reproduce a SPARTA bug)"));
344 fpu,
"Dummy node under top.cpu.core0.fpu (to reproduce a SPARTA bug)"));
347void ExampleSimulator::configureTree_()
349 validateTreeNodeExtensions_();
357 dispatch_baz_->readParams();
358 fpu_baz_->readParams();
365 if(instruction_limit_ != 0){
370 this->
getRoot()->getSearchScope()->getChild(
"top.cpu.core0.rob"),
371 "testing_notif_channel",
372 "Notification channel for testing purposes only",
373 "testing_notif_channel"));
376 getRoot()->getSearchScope()->getChild(
"top.cpu.core0.rob"),
378 "Notification channel for testing report toggling on/off (statistics profiling)",
383 "all_threads_warmup_instruction_count_retired_re4",
384 "Legacy notificiation channel for testing purposes only",
385 "all_threads_warmup_instruction_count_retired_re4"));
387 getRoot()->REGISTER_FOR_NOTIFICATION(
388 onTriggered_, std::string,
"sparta_expression_trigger_fired");
389 on_triggered_notifier_registered_ =
true;
392void ExampleSimulator::bindTree_()
399 auto cpu_factory = getCPUFactory_();
400 cpu_factory->bindTree(
getRoot());
402 sparta::SpartaHandler cb = sparta::SpartaHandler::from_member<
404 this,
"ExampleSimulator::postRandomNumber_");
406 random_number_trigger_.reset(
new sparta::trigger::ExpressionCounterTrigger(
407 "RandomNumber", cb,
"cpu.core0.rob.stats.total_number_retired 7500",
false, this->
getRoot()));
409 toggle_notif_trigger_.reset(
new sparta::trigger::ExpressionTimeTrigger(
415 static const uint32_t warmup_multiplier = 1000;
416 auto gen_expression = [](
const uint32_t core_idx) {
417 std::ostringstream oss;
418 oss <<
"cpu.core" << core_idx <<
".rob.stats.total_number_retired >= "
419 << ((core_idx+1) * warmup_multiplier);
423 num_cores_still_warming_up_ = num_cores_;
424 core_warmup_listeners_.reserve(num_cores_);
426 for (uint32_t core_idx = 0; core_idx < num_cores_; ++core_idx) {
427 core_warmup_listeners_.emplace_back(
428 new sparta::trigger::ExpressionTrigger(
429 "LegacyWarmupNotifications",
431 gen_expression(core_idx),
437void ExampleSimulator::onLegacyWarmupNotification_()
440 --num_cores_still_warming_up_;
441 if (num_cores_still_warming_up_ == 0) {
442 legacy_warmup_report_starter_->postNotification(1);
446const sparta::CounterBase* ExampleSimulator::findSemanticCounter_(CounterSemantic sem)
const {
456void ExampleSimulator::postRandomNumber_()
458 const size_t random = rand() % 25;
459 testing_notification_source_->postNotification(random);
460 random_number_trigger_->reschedule();
463void ExampleSimulator::postToToggleTrigger_()
465 typedef std::pair<uint64_t,uint64_t> ValueCount;
466 static std::queue<ValueCount> values;
468 if (values.empty()) {
475 ValueCount tmp = values.front();
479 if (values.front().second == 0) {
481 ValueCount tmp = values.front();
484 --values.front().second;
487 const ValueCount & current_value = values.front();
488 const uint64_t value_to_post = current_value.first;
489 toggle_trigger_notification_source_->postNotification(value_to_post);
490 toggle_notif_trigger_->reschedule();
493void ExampleSimulator::onTriggered_(
const std::string & msg)
495 std::cout <<
" [trigger] " << msg << std::endl;
498template <
typename ParamT>
501 const std::string& param_name,
502 const std::string& ext_name)
508 sparta::TreeNode::ExtensionsBase * ext = ext_name.empty() ?
537template <
typename ExtensionT>
538ExtensionT* ExampleSimulator::getExtension_(
540 const std::string& ext_name)
542 static_assert(std::is_base_of<sparta::TreeNode::ExtensionsBase, ExtensionT>::value,
543 "ExtensionT must be derived from sparta::TreeNode::ExtensionsBase");
549 return ext_name.empty() ?
551 dynamic_cast<ExtensionT*
>(node->
getExtension(ext_name));
554void ExampleSimulator::validateTreeNodeExtensions_()
557 if (
auto prm = getExtensionParameter_<std::string>(
558 getRoot()->getChild(
"cpu.core0.lsu"),
"name_",
"cat"))
560 prm->addDependentValidationCallback(
563 },
"Parameter 'name_' should be 'Tom'");
567 if (
auto prm = getExtensionParameter_<std::string>(
568 getRoot()->getChild(
"cpu.core0.lsu"),
"language_",
"cat"))
570 prm->addDependentValidationCallback(
572 return val ==
"meow" || val ==
"grrr";
573 },
"Parameter 'language_' should be 'meow' or 'grrr'");
577 if (
auto prm = getExtensionParameter_<std::string>(
578 getRoot()->getChild(
"cpu.core0.lsu"),
"name_",
"mouse"))
580 prm->addDependentValidationCallback(
582 return val ==
"Jerry";
583 },
"Parameter 'name_' should be 'Jerry'");
587 if (
auto prm = getExtensionParameter_<std::string>(
588 getRoot()->getChild(
"cpu.core0.lsu"),
"language_",
"mouse"))
590 prm->addDependentValidationCallback(
592 return val ==
"squeak";
593 },
"Parameter 'language_' should be 'squeak'");
597 if (
auto prm = getExtensionParameter_<std::string>(
598 getRoot()->getChild(
"cpu.core0.fpu"),
"color_",
"circle"))
600 prm->addDependentValidationCallback(
602 return val ==
"green";
603 },
"Parameter 'color_' should be 'green'");
607 if (
auto prm = getExtensionParameter_<std::string>(
608 getRoot()->getChild(
"cpu.core0.fpu"),
"shape_",
"circle"))
610 prm->addDependentValidationCallback(
612 return val ==
"round";
613 },
"Parameter 'shape_' should be 'round'");
617 if (
auto prm = getExtensionParameter_<double>(
618 getRoot()->getChild(
"cpu.core0.fpu"),
"degrees_",
"circle"))
620 prm->addDependentValidationCallback(
623 },
"Parameter 'degrees_' should be 360.0");
627 getExtension_<CircleExtensions>(
getRoot()->getChild(
"cpu.core0.fpu"),
"circle")->doSomethingElse();
630 if (
auto prm = getExtensionParameter_<std::string>(
633 prm->addDependentValidationCallback(
636 },
"Parameter 'color_' should be 'red'");
646 if (core0_lsu->getNumExtensions() > 1) {
649 getExtension_<>(core0_lsu);
656 "call to TreeNode::getExtension()");
661 if (
auto prm = getExtensionParameter_<std::string>(
662 getRoot()->getChild(
"cpu.core0.fpu"),
"color_"))
664 prm->addDependentValidationCallback(
666 return val ==
"green";
667 },
"Parameter 'color_' should be 'green'");
671 if (
auto prm = getExtensionParameter_<std::string>(
672 getRoot()->getChild(
"cpu.core0.fpu"),
"shape_"))
674 prm->addDependentValidationCallback(
676 return val ==
"round";
677 },
"Parameter 'shape_' should be 'round'");
681 if (
auto prm = getExtensionParameter_<double>(
682 getRoot()->getChild(
"cpu.core0.fpu"),
"degrees_"))
684 prm->addDependentValidationCallback(
687 },
"Parameter 'degrees_' should be 360.0");
691 if (
auto prm = getExtensionParameter_<std::string>(
692 getRoot()->getChild(
"cpu.core0.fpu"),
"edges_"))
694 prm->addDependentValidationCallback(
697 },
"Parameter 'edges_' should be '0'");
701 if (
auto prm = getExtensionParameter_<std::string>(
702 getRoot()->getChild(
"cpu.core0.dispatch.baz_node",
false),
"ticket_",
"baz_ext"))
704 prm->addDependentValidationCallback(
707 },
"Parameter 'ticket_' should be '663'");
711ExampleSimulator::ExampleController::ExampleController(
713 sparta::app::Simulation::SimulationController(sim)
715 sparta::app::Simulation::SimulationController::addNamedCallback_(
718 sparta::app::Simulation::SimulationController::addNamedCallback_(
724 std::cout <<
" [control] Controller PAUSE method has been called for simulation '"
730 std::cout <<
" [control] Controller RESUME method has been called for simulation '"
736 std::cout <<
" [control] Controller TERMINATE method has been called for simulation '"
741void ExampleSimulator::ExampleController::customEatCallback_()
743 std::cout <<
" [control] Controller CUSTOM method has been called ('eat')" << std::endl;
746void ExampleSimulator::ExampleController::customSleepCallback_()
748 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.
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.
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.
const Parameter< ContentT > & getParameterAs(const std::string &name) const
Retrieves a sparta::Parameter<ContentT> reference from this parameter set.
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.
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
ExtensionsBase * getExtension(const std::string &extension_name, bool no_factory_ok=false)
Get an extension object by type string. Returns nullptr if not found (unrecognized).
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
ExtensionsBase * createExtension(const std::string &extension_name, bool replace=false)
Create an extension on demand. This is useful if you want to add an extension to a node that was not ...
TreeNode()=delete
Not default-constructable.
ExtensionsBase * getExtension()
Get an extension without needing to specify any particular extension name. If no extensions exist,...
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...
void addTreeNodeExtensionFactory_(const std::string &extension_name, std::function< TreeNode::ExtensionsBase *()> factory)
Include an extension factory for this simulation's device tree nodes. They will be given to specific ...
@ 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 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.