The Sparta Modeling Framework
Loading...
Searching...
No Matches
DataPort.hpp
Go to the documentation of this file.
1// <Port> -*- C++ -*-
2
3
10#pragma once
11
12#include <set>
13#include <vector>
14
15#include "sparta/ports/Port.hpp"
22
23namespace sparta
24{
25
27 // Data Ports
29
30 // Forward declaration
31 template<class DataT>
32 class DataInPort;
33
75 template<class DataT>
76 class DataOutPort final : public OutPort
77 {
78 public:
80 typedef DataT DataType;
81
91 DataOutPort(TreeNode* portset, const std::string & name,
92 bool presume_zero_delay = true) :
93 OutPort(portset, name, presume_zero_delay)
94 {
95 sparta_assert(name.length() != 0, "You cannot have an unnamed port.");
96 sparta_assert(getClock() != nullptr, "DataOutPort '" << name << "' created without a clock");
97 }
98
100 DataOutPort(const DataOutPort &) = delete;
101
103 DataOutPort & operator=(const DataOutPort &) = delete;
104
115 void bind(Port * in) override
116 {
117 DataInPort<DataT> * inp;
118 if((inp = dynamic_cast<DataInPort<DataT> *>(in)) == 0) {
119 throw SpartaException("ERROR: Attempt to bind DataInPort of a disparate types: '" +
120 in->getLocation() + "' to '" + getLocation() + "'");
121 }
122 OutPort::bind(in);
123 bound_in_ports_.push_back(inp);
124 }
125
127 using Port::bind;
128
145 void send(const DataT & dat, sparta::Clock::Cycle rel_time = 0)
146 {
147 sparta_assert(!bound_in_ports_.empty(),
148 "ERROR! Attempt to send data on unbound port: " << getLocation());
149 for(DataInPort<DataT>* itr : bound_in_ports_) {
150 itr->send_(dat, rel_time);
151 }
152 }
153
163 bool isDriven(Clock::Cycle rel_cycle) const override {
164 for(DataInPort<DataT>* itr : bound_in_ports_) {
165 if(itr->isDriven(rel_cycle)) {
166 return true;
167 }
168 }
169 return false;
170 }
171
176 bool isDriven() const override {
177 for(DataInPort<DataT>* itr : bound_in_ports_) {
178 if(itr->isDriven()) {
179 return true;
180 }
181 }
182 return false;
183 }
184
193 uint32_t cancel()
194 {
195 uint32_t cancel_cnt = 0;
196 for(DataInPort<DataT>* itr : bound_in_ports_) {
197 cancel_cnt += itr->cancel();
198 }
199 return cancel_cnt;
200 }
201
212 uint32_t cancelIf(const DataT & criteria) {
213 uint32_t cancel_cnt = 0;
214 for(DataInPort<DataT>* itr : bound_in_ports_) {
215 cancel_cnt += itr->cancelIf(criteria);
216 }
217 return cancel_cnt;
218 }
219
230 uint32_t cancelIf(std::function<bool(const DataT &)> compare) {
231 uint32_t cancel_cnt = 0;
232 for(DataInPort<DataT>* itr : bound_in_ports_) {
233 cancel_cnt += itr->cancelIf(compare);
234 }
235 return cancel_cnt;
236 }
237
238 private:
240 std::vector <DataInPort<DataT>*> bound_in_ports_;
241 };
242
287 template<class DataT>
288 class DataInPort final : public InPort, public DataContainer<DataT>
289 {
290 // Pipeline collection type
292
293 public:
294
296 typedef DataT DataType;
297
307 DataInPort(TreeNode* portset, const std::string & name,
308 sparta::SchedulingPhase delivery_phase, sparta::Clock::Cycle delay) :
309 InPort(portset, name, delivery_phase),
310 DataContainer<DataT>(getClock()),
311 data_in_port_events_(this),
312 port_delay_(delay)
313 {
314 receiver_clock_ = getClock();
315 scheduler_ = receiver_clock_->getScheduler();
316
317 sparta_assert(receiver_clock_ != nullptr,
318 "DataInPort " << name << " does not have a clock");
319 sparta_assert(name.length() != 0, "You cannot have an unnamed port.");
320
321 user_payload_delivery_.reset(new PhasedPayloadEvent<DataT>(&data_in_port_events_, name + "_forward_event",
322 delivery_phase,
323 CREATE_SPARTA_HANDLER_WITH_DATA(DataInPort<DataT>, receivePortData_, DataT)));
324 }
325
342 DataInPort(TreeNode* portset, const std::string & name, sparta::Clock::Cycle delay = 0) :
343 DataInPort(portset, name, (delay == 0 ? sparta::SchedulingPhase::Tick : sparta::SchedulingPhase::PortUpdate), delay)
344 {}
345
347 DataInPort(const DataInPort &) = delete;
348
350 DataInPort & operator=(const DataInPort &) = delete;
351
353 void bind(Port * out) override
354 {
355 DataOutPort<DataT> * outp;
356 if((outp = dynamic_cast<DataOutPort<DataT> *>(out)) == 0) {
357 throw SpartaException("ERROR: Attempt to bind DataOutPort of a disparate types: '" +
358 out->getLocation() + "' to '" + getLocation() + "'");
359 }
360 InPort::bind(out);
361 }
362
364 using Port::bind;
365
370 Clock::Cycle getPortDelay() const override final {
371 return port_delay_;
372 }
373
376 void setContinuing(bool continuing) override final {
377 Port::setContinuing(continuing);
378 user_payload_delivery_->getScheduleable().setContinuing(continuing);
379 }
380
390 bool isDriven(Clock::Cycle rel_cycle) const override {
391 return user_payload_delivery_->isScheduled(rel_cycle);
392 }
393
399 bool isDriven() const override {
400 return user_payload_delivery_->isScheduled();
401 }
402
411 uint32_t cancel() {
412 return user_payload_delivery_->cancel();
413 }
414
425 uint32_t cancelIf(const DataT & criteria) {
426 return user_payload_delivery_->cancelIf(criteria);
427 }
428
439 uint32_t cancelIf(std::function<bool(const DataT &)> compare) {
440 return user_payload_delivery_->cancelIf(compare);
441 }
442
447 void enableCollection(TreeNode* node) override {
448 collector_.reset(new CollectorType(node, Port::name_, 0,
449 "Data being received on this DataInPort"));
450 }
451
452 private:
453
454 Scheduleable & getScheduleable_() override final {
455 return user_payload_delivery_->getScheduleable();
456 }
457
458 void setProducerPrecedence_(Scheduleable * pd) override final {
459 if(pd->getSchedulingPhase() == user_payload_delivery_->getSchedulingPhase()) {
460 pd->precedes(user_payload_delivery_->getScheduleable(), "Port::bind of OutPort to " + getName() + ": '" +
461 pd->getLabel() + "' is a registered driver");
462 }
463 }
464
465 void registerConsumerHandler_(const SpartaHandler & handler) override final
466 {
467 sparta_assert(handler.argCount() == 1,
468 "DataInPort: " << getName()
469 << ": The handler associated with the DataInPort must take at least one argument: "
470 << handler.getName());
471 handler_name_ = getName() + "<DataInPort>[" + handler.getName() + "]";
472 user_payload_delivery_->getScheduleable().setLabel(handler_name_.c_str());
473 }
474
475 void bind_(Port * outp) override final
476 {
477 InPort::bind_(outp);
478 for(auto & consumer : port_consumers_)
479 {
480 if(consumer->getSchedulingPhase() == user_payload_delivery_->getSchedulingPhase()) {
481 user_payload_delivery_->getScheduleable().precedes(consumer, "Port::bind(" + getName() + "->" + outp->getName() + "),'"
482 + consumer->getLabel() + "' is registered consumer");
483 }
484 }
485 }
486
488 friend class DataOutPort<DataT>;
489
504 void send_(const DataT & dat, sparta::Clock::Cycle rel_time)
505 {
506 const uint32_t total_delay = rel_time + port_delay_;
507
508 // Most of the time there is a delay.
509 if(SPARTA_EXPECT_FALSE(total_delay == 0))
510 {
511 checkSchedulerPhaseForZeroCycleDelivery_(user_payload_delivery_->getSchedulingPhase());
512 if(user_payload_delivery_->getSchedulingPhase() == scheduler_->getCurrentSchedulingPhase()) {
513 // Receive the port data now
514 receivePortData_(dat);
515 return;
516 }
517 }
518 user_payload_delivery_->preparePayload(dat)->schedule(total_delay, receiver_clock_);
519 }
520
522 sparta::EventSet data_in_port_events_;
523
525 std::unique_ptr<PhasedPayloadEvent<DataT>> user_payload_delivery_;
526
528 std::string handler_name_;
529
531 const Clock * receiver_clock_ = nullptr;
532
534 std::unique_ptr<CollectorType> collector_;
535
537 void receivePortData_(const DataT & dat)
538 {
541 explicit_consumer_handler_((const void*)&dat);
542 }
543 if(SPARTA_EXPECT_FALSE(collector_ != nullptr)) {
544 if(SPARTA_EXPECT_FALSE(collector_->isCollected())) {
545 collector_->collect(dat);
546 }
547 }
548 }
549
551 const Clock::Cycle port_delay_;
552 };
553}
554
555
556
Implementation of the Collectable class that allows a user to collect an object into an pipeViewer pi...
File that defines the DataContainer class.
File that defines the EventSet class.
File that defines the PayloadEvent class.
File that defines the Port base class.
File that defines Precedence operator>> rules between EventNode types.
File that defines the Scheduleable class.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
#define SPARTA_EXPECT_TRUE(x)
A macro for hinting to the compiler a particular condition should be considered most likely true.
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
#define CREATE_SPARTA_HANDLER_WITH_DATA(clname, meth, dataT)
Scheduler * getScheduler() const
Definition Clock.hpp:302
Used by DataInPort and SyncInPort, this class holds received data from these ports and remembers the ...
void setData_(const DataT &dat)
Set the data received.
DataInPort receives data from sender using a DataOutPort.
Definition DataPort.hpp:289
Clock::Cycle getPortDelay() const override final
Get the port delay associated with this port.
Definition DataPort.hpp:370
DataInPort(TreeNode *portset, const std::string &name, sparta::Clock::Cycle delay=0)
Construct a DataInPort with a default delivery phase based on the delay.
Definition DataPort.hpp:342
uint32_t cancelIf(const DataT &criteria)
Cancel any scheduled Payload that matches the given criteria.
Definition DataPort.hpp:425
DataInPort(TreeNode *portset, const std::string &name, sparta::SchedulingPhase delivery_phase, sparta::Clock::Cycle delay)
Construct a DataInPort with a specific delivery phase.
Definition DataPort.hpp:307
void enableCollection(TreeNode *node) override
Enable pipeline collection.
Definition DataPort.hpp:447
uint32_t cancelIf(std::function< bool(const DataT &)> compare)
Cancel any scheduled Payload that matches the given function.
Definition DataPort.hpp:439
DataT DataType
Expected typedef for DataT.
Definition DataPort.hpp:296
uint32_t cancel()
Cancel all outstanding incoming data not delivered
Definition DataPort.hpp:411
bool isDriven() const override
Is this Port driven at all?
Definition DataPort.hpp:399
bool isDriven(Clock::Cycle rel_cycle) const override
Determine if this DataInPort is driven on the given cycle.
Definition DataPort.hpp:390
DataInPort & operator=(const DataInPort &)=delete
No assignments.
void setContinuing(bool continuing) override final
Do events from this port keep simulation going?
Definition DataPort.hpp:376
DataInPort(const DataInPort &)=delete
No making copies.
void bind(Port *out) override
Check the Data types.
Definition DataPort.hpp:353
DataOutPort is used for transferring any data to another module.
Definition DataPort.hpp:77
DataT DataType
A typedef for the type of data this port passes.
Definition DataPort.hpp:80
DataOutPort(const DataOutPort &)=delete
No making copies!
uint32_t cancel()
Cancel all outstanding port sends regardless of criteria.
Definition DataPort.hpp:193
bool isDriven(Clock::Cycle rel_cycle) const override
Determine if this DataOutPort has any connected DataInPort where the data is to be delivered on the g...
Definition DataPort.hpp:163
uint32_t cancelIf(const DataT &criteria)
Cancel any scheduled Payload that matches the given criteria.
Definition DataPort.hpp:212
DataOutPort(TreeNode *portset, const std::string &name, bool presume_zero_delay=true)
Construct a DataOutPort within the given PortSet.
Definition DataPort.hpp:91
void bind(Port *in) override
Bind to an DataInPort.
Definition DataPort.hpp:115
DataOutPort & operator=(const DataOutPort &)=delete
No making assignments!
uint32_t cancelIf(std::function< bool(const DataT &)> compare)
Cancel any scheduled Payload that matches the given function.
Definition DataPort.hpp:230
bool isDriven() const override
Does this DataOutPort have any DataInPort's where the data is not yet delivered?
Definition DataPort.hpp:176
void send(const DataT &dat, sparta::Clock::Cycle rel_time=0)
Send data to bound receivers.
Definition DataPort.hpp:145
Set of Events that a unit (or sparta::TreeNode, sparta::Resource) contains and are visible through a ...
Definition EventSet.hpp:26
Base class for all InPort types.
Definition Port.hpp:297
Scheduler * scheduler_
The scheduler used.
Definition Port.hpp:481
void bind(Port *out) override
Bind to an OutPort.
Definition Port.hpp:386
void checkSchedulerPhaseForZeroCycleDelivery_(const sparta::SchedulingPhase &user_callback_phase)
Common method for checking phasing.
Definition Port.hpp:456
virtual void bind_(Port *outp)
Called by the OutPort, remember the binding.
Definition Port.hpp:451
ScheduleableList port_consumers_
Definition Port.hpp:478
Base class for all OutPort types.
Definition Port.hpp:493
void bind(Port *in) override
Bind to an InPort.
Definition Port.hpp:575
Class to schedule a Scheduleable in the future with a payload, but the class itself is not typed on t...
The port interface used to bind port types together and defines a port behavior.
Definition Port.hpp:59
const std::string name_
The name of this port.
Definition Port.hpp:282
virtual void bind(Port *port)=0
Method to bind this Port to another, pointer style.
SpartaHandler explicit_consumer_handler_
Explicit consumer handler registered via registerConsumerHandler.
Definition Port.hpp:288
virtual void setContinuing(bool continuing)
Definition Port.hpp:218
A class that defines the basic scheduling interface to the Scheduler. Not intended to be used by mode...
SchedulingPhase getCurrentSchedulingPhase() const
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
std::string getLocation() const override final
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.
Class used to either manually or auto-collect an Annotation String object in a pipeline database.
Macros for handling exponential backoff.
SchedulingPhase
The SchedulingPhases used for events (Tick, Update, PortUpdate, etc)
@ PortUpdate
N-cycle Ports are updated in this phase.
@ Tick
Most operations (combinational logic) occurs in this phase.