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 "simdb_fwd.hpp"
28#include "simdb/schema/DatabaseTypedefs.hpp"
29#include "sparta/statistics/CounterBase.hpp"
53 typedef std::shared_ptr<Clock> Handle;
54 typedef uint32_t Period;
55 typedef uint64_t Cycle;
56 typedef double Frequency;
59 static bool normalized_;
60 typedef std::list<Clock*> RefList;
94 Clock(
const std::string& name,
const Handle& parent_clk,
95 const uint32_t& p_rat = 1,
const uint32_t& c_rat = 1);
101 Clock(
const std::string& name,
const Handle& parent,
double frequency_mhz);
112 void setRatio(
const uint32_t& p_rat = 1,
const uint32_t& c_rat = 1);
116 return frequency_mhz_;
122 return parent_ratio_;
128 if (parent_ !=
nullptr) {
129 root_ratio_ = parent_ratio_.inv() * parent_->root_ratio_;
132 partial_norm = utils::lcm(partial_norm, root_ratio_.getDenominator());
133 for (
auto i = children_.begin(); i != children_.end(); ++i) {
134 partial_norm = utils::lcm(partial_norm, (*i)->calcNorm(partial_norm));
148 "Should not be setting period on a sparta::Clock after device tree finalization");
149 period_ = uint32_t(root_ratio_ * norm);
168 return (tick / period_);
197 elapsed_cycles_ =
getCycle(elapsed_ticks);
206 return elapsed_cycles_;
216 return cycle * period_;
226 return static_cast<Scheduler::Tick>(cycle *
static_cast<double>(period_));
236 return ((abs_cycle - 1) * period_);
253 explicit operator std::string()
const
255 std::stringstream ss;
257 <<
" period=" << period_;
258 if (frequency_mhz_ != 0.0) {
259 ss <<
" freq=" << frequency_mhz_;
261 if (parent_ !=
nullptr) {
262 ss <<
" (" << std::string(parent_ratio_)
263 <<
" to " << parent_->getName() <<
")";
272 os <<
"Clock(" <<
getName() <<
"):" << std::endl;
273 if (parent_ !=
nullptr) {
274 os <<
"\tRatio to Clock(" << parent_->getName() <<
"): "
275 << parent_ratio_ << std::endl;
277 os <<
"\tROOT Clock" << std::endl;
279 os <<
"\tRatio to ROOT: " << root_ratio_ << std::endl
280 <<
"\tPeriod: " << period_ << std::endl;
281 if (frequency_mhz_ != 0.0) {
282 os <<
"\tFrequency: " << frequency_mhz_ << std::endl;
291 simdb::DatabaseID
serializeTo(
const simdb::ObjectManager & sim_db)
const;
294 virtual std::string
stringize(
bool pretty=
false)
const override {
296 return (std::string)*
this;
316 return cycles_roctr_;
323 return cycles_roctr_;
337 const double frequency_mhz_ = 0.0;
338 Cycle elapsed_cycles_ = 0;
340 class CurrentCycleCounter :
public ReadOnlyCounter {
343 CurrentCycleCounter(Clock& clk, StatisticSet* parent) :
344 ReadOnlyCounter(parent,
346 "Cycle Count of this Clock",
356 return clk_.currentCycle();
358 } cycles_roctr_ = {*
this, &sset_};
366 void recursSerializeToTable_(
367 simdb::TableRef & clock_tbl,
368 const simdb::DatabaseID parent_clk_id,
369 std::map<const Clock*, simdb::DatabaseID> & db_ids)
const;
398 sparta_assert(src_clk,
"calculateClockCrossingDelay requires a non-null src_clk");
399 sparta_assert(dst_clk,
"calculateClockCrossingDelay requires a non-null dst_clk");
400 sparta_assert(src_clk->getScheduler() == dst_clk->getScheduler(),
401 "calculateClockCrossingDelay requires src_clk and dst_clk to operate on "
402 "the same scheduler. src = " << src_clk->getScheduler() <<
" and dst = "
403 << dst_clk->getScheduler());
404 auto scheduler = src_clk->getScheduler();
406 "calculateClockCrossingDelay requires src_clk (" << *src_clk <<
") to "
407 "have a non-null scheduler");
424 current_tick / src_clk->getPeriod() * src_clk->getPeriod();
427 num_delay_ticks += src_delay + dst_delay;
431 raw_event_arrival_tick / dst_clk->getPeriod() * dst_clk->getPeriod();
432 if (raw_event_arrival_tick != raw_dst_clk_posedge_tick) {
433 sparta_assert(raw_event_arrival_tick > raw_dst_clk_posedge_tick);
434 num_delay_ticks += dst_clk->getPeriod() - (raw_event_arrival_tick - raw_dst_clk_posedge_tick);
437 return num_delay_ticks;
458 sparta_assert(src_clk,
"calculateReverseClockCrossingDelay requires a non-null src_clk");
459 sparta_assert(dst_clk,
"calculateReverseClockCrossingDelay requires a non-null dst_clk");
460 sparta_assert(src_clk->getScheduler() == dst_clk->getScheduler(),
461 "calculateReverseClockCrossingDelay requires src_clk and dst_clk to operate on "
462 "the same scheduler. src = " << src_clk->getScheduler() <<
" and dst = "
463 << dst_clk->getScheduler());
464 auto scheduler = src_clk->getScheduler();
466 "calculateReverseClockCrossingDelay requires src_clk (" << *src_clk <<
") to "
467 "have a non-null scheduler");
473 dst_arrival_tick / dst_clk->getPeriod() * dst_clk->getPeriod();
478 relative_ticks_before_arrival += src_delay + dst_delay;
483 raw_event_sent_tick / src_clk->getPeriod() * src_clk->getPeriod();
485 if (raw_event_sent_tick != raw_src_clk_posedge_tick) {
486 sparta_assert(raw_event_sent_tick > raw_src_clk_posedge_tick);
487 relative_ticks_before_arrival += (raw_event_sent_tick - raw_src_clk_posedge_tick);
490 return relative_ticks_before_arrival;
497#define SPARTA_CLOCK_BODY \
499 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...
simdb::DatabaseID serializeTo(const simdb::ObjectManager &sim_db) const
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...
TreeNode which represents the root ("top") of a device tree.
A class that lets you schedule events now and in the future.
Tick getCurrentTick() const noexcept
The current tick the Scheduler is working on or just finished.
uint64_t Tick
Typedef for our unit of time.
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