23#include "sparta/statistics/Counter.hpp"
24#include "sparta/statistics/ReadOnlyCounter.hpp"
25#include "sparta/utils/Rational.hpp"
26#include "sparta/utils/MathUtils.hpp"
27#include "sparta/statistics/CounterBase.hpp"
46 typedef std::shared_ptr<Clock> Handle;
47 typedef uint32_t Period;
48 typedef uint64_t Cycle;
49 typedef double Frequency;
52 static bool normalized_;
53 typedef std::list<Clock*> RefList;
87 Clock(
const std::string& name,
const Handle& parent_clk,
88 const uint32_t& p_rat = 1,
const uint32_t& c_rat = 1);
94 Clock(
const std::string& name,
const Handle& parent,
double frequency_mhz);
105 void setRatio(
const uint32_t& p_rat = 1,
const uint32_t& c_rat = 1);
109 return frequency_mhz_;
115 return parent_ratio_;
121 if (parent_ !=
nullptr) {
122 root_ratio_ = parent_ratio_.inv() * parent_->root_ratio_;
125 partial_norm = utils::lcm(partial_norm, root_ratio_.getDenominator());
126 for (
auto i = children_.begin(); i != children_.end(); ++i) {
127 partial_norm = utils::lcm(partial_norm, (*i)->calcNorm(partial_norm));
141 "Should not be setting period on a sparta::Clock after device tree finalization");
142 period_ = uint32_t(root_ratio_ * norm);
161 return (tick / period_);
190 elapsed_cycles_ =
getCycle(elapsed_ticks);
199 return elapsed_cycles_;
209 return cycle * period_;
219 return static_cast<Scheduler::Tick>(cycle *
static_cast<double>(period_));
229 return ((abs_cycle - 1) * period_);
246 explicit operator std::string()
const
248 std::stringstream ss;
250 <<
" period=" << period_;
251 if (frequency_mhz_ != 0.0) {
252 ss <<
" freq=" << frequency_mhz_;
254 if (parent_ !=
nullptr) {
255 ss <<
" (" << std::string(parent_ratio_)
256 <<
" to " << parent_->getName() <<
")";
265 os <<
"Clock(" <<
getName() <<
"):" << std::endl;
266 if (parent_ !=
nullptr) {
267 os <<
"\tRatio to Clock(" << parent_->getName() <<
"): "
268 << parent_ratio_ << std::endl;
270 os <<
"\tROOT Clock" << std::endl;
272 os <<
"\tRatio to ROOT: " << root_ratio_ << std::endl
273 <<
"\tPeriod: " << period_ << std::endl;
274 if (frequency_mhz_ != 0.0) {
275 os <<
"\tFrequency: " << frequency_mhz_ << std::endl;
281 virtual std::string
stringize(
bool pretty=
false)
const override {
283 return (std::string)*
this;
303 return cycles_roctr_;
310 return cycles_roctr_;
324 const double frequency_mhz_ = 0.0;
325 Cycle elapsed_cycles_ = 0;
327 class CurrentCycleCounter :
public ReadOnlyCounter {
330 CurrentCycleCounter(
Clock& clk, StatisticSet* parent) :
333 "Cycle Count of this Clock",
343 return clk_.currentCycle();
345 } cycles_roctr_ = {*
this, &sset_};
374 sparta_assert(src_clk,
"calculateClockCrossingDelay requires a non-null src_clk");
375 sparta_assert(dst_clk,
"calculateClockCrossingDelay requires a non-null dst_clk");
376 sparta_assert(src_clk->getScheduler() == dst_clk->getScheduler(),
377 "calculateClockCrossingDelay requires src_clk and dst_clk to operate on "
378 "the same scheduler. src = " << src_clk->getScheduler() <<
" and dst = "
379 << dst_clk->getScheduler());
380 auto scheduler = src_clk->getScheduler();
382 "calculateClockCrossingDelay requires src_clk (" << *src_clk <<
") to "
383 "have a non-null scheduler");
400 current_tick / src_clk->getPeriod() * src_clk->getPeriod();
403 num_delay_ticks += src_delay + dst_delay;
407 raw_event_arrival_tick / dst_clk->getPeriod() * dst_clk->getPeriod();
408 if (raw_event_arrival_tick != raw_dst_clk_posedge_tick) {
409 sparta_assert(raw_event_arrival_tick > raw_dst_clk_posedge_tick);
410 num_delay_ticks += dst_clk->getPeriod() - (raw_event_arrival_tick - raw_dst_clk_posedge_tick);
413 return num_delay_ticks;
434 sparta_assert(src_clk,
"calculateReverseClockCrossingDelay requires a non-null src_clk");
435 sparta_assert(dst_clk,
"calculateReverseClockCrossingDelay requires a non-null dst_clk");
436 sparta_assert(src_clk->getScheduler() == dst_clk->getScheduler(),
437 "calculateReverseClockCrossingDelay requires src_clk and dst_clk to operate on "
438 "the same scheduler. src = " << src_clk->getScheduler() <<
" and dst = "
439 << dst_clk->getScheduler());
440 auto scheduler = src_clk->getScheduler();
442 "calculateReverseClockCrossingDelay requires src_clk (" << *src_clk <<
") to "
443 "have a non-null scheduler");
449 dst_arrival_tick / dst_clk->getPeriod() * dst_clk->getPeriod();
454 relative_ticks_before_arrival += src_delay + dst_delay;
459 raw_event_sent_tick / src_clk->getPeriod() * src_clk->getPeriod();
461 if (raw_event_sent_tick != raw_src_clk_posedge_tick) {
462 sparta_assert(raw_event_sent_tick > raw_src_clk_posedge_tick);
463 relative_ticks_before_arrival += (raw_event_sent_tick - raw_src_clk_posedge_tick);
466 return relative_ticks_before_arrival;
473#define SPARTA_CLOCK_BODY \
475 bool Clock::normalized_ = false; \
A simple time-based, event precedence based scheduler.
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Exception class for all of Sparta.
File that defines the StatisticSet class.
Basic Node framework in sparta device tree composite pattern.
A representation of simulated time.
Cycle currentCycle() const
Get the current cycle (uses current tick from the Scheduler)
utils::Rational< uint32_t > getRatio() const
Get the clock ratio.
Scheduler::Tick currentTick() const
Get the current scheduler tick.
virtual std::string stringize(bool pretty=false) const override
Create a string representation of this node.
void associate(const Handle &parent)
Associate this clock with another clock.
Clock(const std::string &name, const Handle &parent_clk, const uint32_t &p_rat=1, const uint32_t &c_rat=1)
Construct a named clock with a clock parent and a clock relative to that parent.
Cycle elapsedCycles() const
Return the total elapsed cycles from this Clocks POV.
void setPeriod(uint32_t norm)
Set the period of this clock.
Clock(const std::string &name, const Handle &parent, double frequency_mhz)
Construct with a frequency.
Scheduler::Tick getTick(const double &cycle) const
Return the tick corresponding to the given cycle.
Clock(const std::string &name, Scheduler *scheduler)
Construct a clock.
Clock(RootTreeNode *parent_root, const std::string &name, Scheduler *scheduler)
Construct a named clock with a RootTreeNode as its parent. This will effeclivelly allow this tree (an...
void updateElapsedCycles(const Scheduler::Tick elapsed_ticks)
Update the elapsed_cycles internal value given the number of ticks.
void print(std::ostream &os) const
Used for printing the clock information.
const ReadOnlyCounter & getCyclesROCounter() const
Returns a counter holding the cycle count of this clock.
Period getPeriod() const
Returns the period of this clock in scheduler ticks.
ReadOnlyCounter & getCyclesROCounter()
Returns a counter holding the cycle count of this clock.
double getFrequencyMhz() const
Get the clock frequency.
Scheduler * getScheduler() const
void setRatio(const uint32_t &p_rat=1, const uint32_t &c_rat=1)
Set the ratio of the clock.
Scheduler::Tick getAbsoluteTick(const Cycle &abs_cycle) const
Convert the given absolute cycle number into the corresponding absolute tick number.
Scheduler::Tick getTick(const Cycle &cycle) const
Return the tick corresponding to the given cycle.
~Clock()
Destroy this Clock (deregisters from the Scheduler)
uint32_t calcNorm(uint32_t partial_norm=1)
Calculate the norm.
bool isPosedge() const
Return true if the current tick aligns with a positive edge of this Clock.
Cycle getCycle(const Scheduler::Tick &tick) const
Given the tick, convert to a Clock::Cycle.
uint64_t counter_type
Counter value type.
@ COUNT_NORMAL
Counter counts the number of times something happens like one would expect. This is a weakly monotoni...
virtual bool isFinalized() const
Is this node (and thus the entire tree above it) "finalized".
Represents a non-writable and non-observable counter with a very similar interface to sparta::Counter...
ReadOnlyCounter(TreeNode *parent, const std::string &name, const std::string &group, TreeNode::group_idx_type group_idx, const std::string &desc, CounterBehavior behave, const counter_type *ref, visibility_t visibility)
ReadOnlyCounter constructor.
TreeNode which represents the root ("top") of a device tree.
A class that lets you schedule events now and in the future.
uint64_t Tick
Typedef for our unit of time.
Tick getCurrentTick() const noexcept
The current tick the Scheduler is working on or just finished.
Set of StatisticDef and CounterBase-derived objects for visiblility through a sparta Tree.
Node in a composite tree representing a sparta Tree item.
virtual void setClock(const Clock *clk)
Assigns a clock to this node. This clock will then be accessed by any descendant which has no assigne...
const std::string & getName() const override
Gets the name of this node.
Class to represent a Rational number.
Macros for handling exponential backoff.
std::ostream & operator<<(std::ostream &o, const SimulationInfo &info)
ostream insertion operator for SimulationInfo