13#include <unordered_map>
32 class GlobalOrderingPoint;
95 sparta_assert(name.length() != 0,
"You cannot have an unnamed port.");
97 "Ports must created with a PortSet: " << name);
99 ensureParentIsPortSet_(portset);
162 participate_in_auto_precedence_ = participate;
169 return participate_in_auto_precedence_;
179 std::stringstream ss;
180 ss <<
"[bound to] {";
185 ss << p->getName() <<
" (" << p->getLocation() <<
")";
199 sparta_assert (
"ERROR:Parent port's don't have delays" == 0);
204 sparta_assert (
"ERROR:Parent port's don't have delays" == 0);
209 sparta_assert (
"ERROR:Parent port's don't have delays" == 0);
222#ifndef DO_NOT_DOCUMENT
223 template<
class PObjT,
void * precedes_obj =
nullptr>
224 void precedes(
const PObjT &) {
225 static_assert(precedes_obj !=
nullptr,
226 "You cannot set a precedence on a Port anymore -- use "
227 "registerConsumerEvent and registerProducingEvent instead");
243 virtual bool isDriven(Clock::Cycle rel_cycle)
const {
245 bool NOT_DEFINED =
true;
247 "Function not defined for this Port: " <<
getName());
254 bool NOT_DEFINED =
true;
256 "Function not defined for this Port: " <<
getName());
265 void validateNode_()
const override {
270 void ensureParentIsPortSet_(
TreeNode * parent);
273 bool participate_in_auto_precedence_ =
true;
340 "Only one handler/callback is supported on this port: " <<
getName() <<
342 " \n\tTrying to register: " << handler.getName());
369 "You cannot register a consumer on an OUT port -- that doesn't make sense: "
370 <<
getName() <<
" consumer being registered: " << consumer.Scheduleable::getLabel());
373 "You cannot register a consuming event after the port is bound. \n\tPort: '"
374 <<
getName() <<
"' Event: '" << consumer.Scheduleable::getLabel() <<
"'"
375 <<
"\n\tIf this is happening from sparta::Unit auto-precedence, set this Port's "
376 <<
"\n\tauto-precedence rule to false by calling the Port's method participateInAutoPrecedence(false)");
390 "' to an inny: '" +
getName() +
"'");
424 "ERROR: You cannot set precedence between two Ports on different phases: "
458 (void) user_callback_phase;
460 "\n\n\tThe currently firing event: '" <<
463 "\n\tand is driving an OutPort that's connected to a zero-cycle Inport: " <<
getLocation() <<
464 "\n\tUnfortunately, this InPort's registered handler '" <<
466 ".\n\n\tThis won't work for a for a zero-cycle out_port->in_port send (where send delay == 0) "
467 "since an event on a higher phase cannot schedule an event on a lower phase within the same cycle."
468 "\n\n\tTo fix this, in the constructor of InPort '" <<
getName() <<
469 "' move the registered handler to at least 'sparta::SchedulingPhase::" <<
471 getName() <<
"(..., sparta::SchedulingPhase::" <<
473 "\tOR you add a cycle delay to the InPort '" <<
getName() <<
"' via its last construction argument.\n\n");
508 bool presume_zero_delay) :
531 "You cannot register a producing event after the port is bound. \n\tPort: '"
532 <<
getName() <<
"' Event: '" << producer.Scheduleable::getLabel() <<
"'"
533 <<
"\n\tIf this is happening from sparta::Unit auto-precedence, set this Port's "
534 <<
"\n\tauto-precedence rule to false by calling the Port's method participateInAutoPrecedence(false)");
559 "You cannot register a producing port after the port is bound. \n\tOutPort: '"
561 <<
"\n\tIf this is happening from sparta::Unit auto-precedence, set this Port's "
562 <<
"\n\tauto-precedence rule to false by calling the Port's method participateInAutoPrecedence(false)");
579 "' to an outty: '" +
getName() +
"'");
584 "Trying to bind two ports that are on different clocks with different freq. "
585 "Recommend using SyncPorts");
590 <<
"' is already bound to '" << in->
getLocation() <<
"' ");
593 if((inp =
dynamic_cast<InPort *
>(in)) == 0) {
595 in->
getName() +
"' to an InPort for some reason...");
621 "Somehow, someway, '" << pd->getLabel() <<
"' is registered "
623 <<
"' and, at the same time, a consumer of Port: '"
625 if(pd->getSchedulingPhase() == cons->getSchedulingPhase()) {
627 pd->precedes(cons, reason);
File that defines the Clock class.
File that defines the Event class.
File that defines the Scheduleable class.
A simple time-based, event precedence based scheduler.
File that defines the phases used in simulation.
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 contains the macro used to generate the class callbacks.
Basic Node framework in sparta device tree composite pattern.
A representation of simulated time.
double getFrequencyMhz() const
Get the clock frequency.
Used to set precedence between Scheduleable types across simulation.
Base class for all InPort types.
Scheduler * scheduler_
The scheduler used.
friend InPort & operator>>(const GlobalOrderingPoint &, InPort &)
Methods used for precedence have access to the internal scheduleable.
void registerConsumerHandler(const SpartaHandler &handler)
Register a handler to this Port (must be Direction::IN) to handle data arrival.
void bind(Port *out) override
Bind to an OutPort.
void registerConsumerEvent(Scheduleable &consumer)
Add an event "listener" to this port.
void checkSchedulerPhaseForZeroCycleDelivery_(const sparta::SchedulingPhase &user_callback_phase)
Common method for checking phasing.
virtual void setProducerPrecedence_(Scheduleable *producer)
void precedes(InPort &consumer)
Ensure data entering this Port is handled before data on another.
sparta::SchedulingPhase getDeliverySchedulingPhase() const
virtual void bind_(Port *outp)
Called by the OutPort, remember the binding.
virtual void registerConsumerHandler_(const sparta::SpartaHandler &)
Let derived classes look over the registered consumer handler.
ScheduleableList port_consumers_
const Clock * receiver_clock_
The receiving clock.
friend OutPort
The OutPort will call bind_ and setProducerPrecedence_.
virtual Scheduleable & getScheduleable_()=0
Return the internally used Scheduleable for precedence.
const ScheduleableList & getPortTickConsumers() const
Get the list of port tick consumers.
InPort(TreeNode *portset, const std::string &name, sparta::SchedulingPhase delivery_phase)
Base class for all InPort types (sparta::DataInPort, sparta::SignalInPort, sparta::SyncInPort)
sparta::SchedulingPhase delivery_phase_
The delivery phase of this InPort.
Base class for all OutPort types.
virtual void registerProducingEvent_(Scheduleable &)
void bind(Port *in) override
Bind to an InPort.
bool presume_zero_delay_
Presume that data sent on this OutPort to be zero-delay.
OutPort(TreeNode *portset, const std::string &name, bool presume_zero_delay)
Base class for all OutPort types (sparta::DataOutPort, sparta::SignalOutPort, sparta::SyncOutPort)
void registerProducingEvent(Scheduleable &producer)
Add an event "producer" to this port.
ScheduleableList port_producers_
void registerProducingPort(InPort &producer)
Add an InPort "producer" to this OutPort.
bool sync_port_
Is this port a syncport?
The port interface used to bind port types together and defines a port behavior.
Port(TreeNode *portset, Direction dir, const std::string &name)
Construct a Port.
void bind(Port &port)
Method to bind this Port to another, reference style.
virtual void participateInAutoPrecedence(bool participate)
Turn on/off auto precedence for this port.
size_t getNumBoundPorts() const
How many ports are bound to this port?
bool isAlreadyBound(const Port *pt)
See if the given port is already bound.
std::string stringize(bool x) const override
Stringize the Port.
const std::string name_
The name of this port.
virtual void setPortDelay(double)
Add a double version for SyncPort.h.
std::vector< Port * > bound_ports_
List of bound ports.
virtual Clock::Cycle getPortDelay() const
Get this Port's static delay.
std::vector< Scheduleable * > ScheduleableList
A convenience typedef.
virtual ~Port()
Destructor.
virtual bool isBound() const
Is this port bound to another port?
virtual void bind(Port *port)=0
Method to bind this Port to another, pointer style.
Direction
The direction of this port.
SpartaHandler explicit_consumer_handler_
Explicit consumer handler registered via registerConsumerHandler.
virtual void enableCollection(TreeNode *)
Enable collection on the port.
virtual bool isDriven(Clock::Cycle rel_cycle) const
Determine if this Port (out or in) is driven on the given cycle.
virtual void setPortDelay(sparta::Clock::Cycle)
Set the delay for a port.
virtual bool isDriven() const
Is this Port driven at all?
virtual bool doesParticipateInAutoPrecedence() const
Does this Port participate in auto-precedence establishment by sparta::Unit?
virtual Direction getDirection() const
The direction of the port.
virtual void setContinuing(bool continuing)
A class that defines the basic scheduling interface to the Scheduler. Not intended to be used by mode...
const char * getLabel() const
Get the internal label.
void precedes(Scheduleable &consumer, const std::string &reason="")
Have this Scheduleable precede another.
SchedulingPhase getSchedulingPhase() const
Get the internal phase number.
A class that lets you schedule events now and in the future.
SchedulingPhase getCurrentSchedulingPhase() const
const Scheduleable * getCurrentFiringEvent() const
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
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
TreeNode()=delete
Not default-constructable.
void addChild(TreeNode *child, bool inherit_phase=true)
Adds a TreeNode to this node as a child.
const Clock * getClock() override
Walks up parents (starting with self) until a parent with an associated local clock is found,...
const std::string & getName() const override
Gets the name of this node.
void setExpectedParent_(const TreeNode *parent)
Tracks a node as an expected parent without actually adding this node as a child. This is used almost...
Macros for handling exponential backoff.
void bind(Bus *p1, Bus *p2)
Bind two buses together.
SchedulingPhase
The SchedulingPhases used for events (Tick, Update, PortUpdate, etc)