The Sparta Modeling Framework
Loading...
Searching...
No Matches
SignalPort.hpp
Go to the documentation of this file.
1// <SignalPort> -*- C++ -*-
2
9#pragma once
10#include <set>
11#include <list>
12#include <unordered_map>
13
14#include "sparta/ports/Port.hpp"
19
20namespace sparta
21{
22
24 // Signal Ports
26
28 class SignalInPort;
29
55 class SignalOutPort final : public OutPort
56 {
57 public:
58
68 SignalOutPort(TreeNode * portset, const std::string & name,
69 bool presume_zero_delay = true) :
70 OutPort(portset, name, presume_zero_delay)
71 {
72 sparta_assert(name.length() != 0, "You cannot have an unnamed port.");
73 }
74
85 void bind(Port * in) override;
86
88 using Port::bind;
89
101 void send(sparta::Clock::Cycle rel_time = 0);
102
104 SignalOutPort(const SignalOutPort &) = delete;
105
108
109 private:
110
112 std::vector <SignalInPort*> bound_in_ports_;
113 };
114
148 class SignalInPort final : public InPort, public DataContainer<bool>
149 {
150 public:
151
158 SignalInPort(TreeNode * portset, const std::string & name,
159 sparta::SchedulingPhase phase, sparta::Clock::Cycle delay) :
160 InPort(portset, name, phase),
161 DataContainer<bool>(getClock()),
162 port_delay_(delay),
163 signal_events_(this)
164 {
167
169 "SignalInPort " << name << " does not have a clock");
170 sparta_assert(name.length() != 0, "You cannot have an unnamed port.");
171 user_signal_delivery_.
172 reset(new PhasedUniqueEvent(&signal_events_, name + "_forward_event",
173 phase, CREATE_SPARTA_HANDLER(SignalInPort, receiveSignal_)));
174 }
175
188 SignalInPort(TreeNode* portset, const std::string & name, sparta::Clock::Cycle delay = 0) :
189 SignalInPort(portset, name, (delay == 0 ?
192 {}
193
195 SignalInPort(const SignalInPort &) = delete;
196
199
210 void bind(Port * out) override;
211
213 using Port::bind;
214
219 Clock::Cycle getPortDelay() const override final {
220 return port_delay_;
221 }
222
225 void setContinuing(bool continuing) override final {
226 // signal_arrive_event_.setContinuing(continuing);
227 user_signal_delivery_->setContinuing(continuing);
228 }
229
230 private:
231
232 Scheduleable & getScheduleable_() override final {
233 return user_signal_delivery_->getScheduleable();
234 }
235
236 void setProducerPrecedence_(Scheduleable * pd) override final {
237 if(pd->getSchedulingPhase() == user_signal_delivery_->getSchedulingPhase()) {
238 pd->precedes(*user_signal_delivery_, "Port::bind of OutPort to " + getName() + ": '" +
239 pd->getLabel() + "' is a registered driver");
240 }
241 }
242
243 void registerConsumerHandler_(const SpartaHandler & handler) override final {
244 sparta_assert(handler.argCount() == 0,
245 "SignalInPort: " << getName()
246 << ": The handler associated with the SignalInPort must not expect an argument: "
247 << handler.getName());
248 // Help the user identify their events/callbacks from the Scheduler debug
249 handler_name_ = getName() + "<SignalInPort>[" + explicit_consumer_handler_.getName() + "]";
250 user_signal_delivery_->setLabel(handler_name_.c_str());
251 }
252
253 // The SignalOutPort will send the transaction over as well as bind
254 friend class SignalOutPort;
255
257 void bind_(Port * out) override final
258 {
259 InPort::bind_(out);
260 for(auto & consumer : port_consumers_)
261 {
262 if(consumer->getSchedulingPhase() == user_signal_delivery_->getSchedulingPhase()) {
263 user_signal_delivery_->precedes(consumer, "Port::bind(" + getName() + "->" + out->getName() + "),'"
264 + consumer->getLabel() + "' is registered driver");
265 }
266 }
267 }
268
283 void send_(sparta::Clock::Cycle rel_time)
284 {
285 const uint32_t total_delay = rel_time + port_delay_;
286 // Most of the time there is a delay.
287 if(SPARTA_EXPECT_FALSE(total_delay == 0))
288 {
289 checkSchedulerPhaseForZeroCycleDelivery_(user_signal_delivery_->getSchedulingPhase());
290 if(user_signal_delivery_->getSchedulingPhase() == scheduler_->getCurrentSchedulingPhase()) {
291 // Receive the port data now
292 receiveSignal_();
293 return;
294 }
295 }
296 user_signal_delivery_->schedule(total_delay, receiver_clock_);
297 }
298
300 const Clock::Cycle port_delay_;
301
303 void receiveSignal_() {
304 // Set's the timestamp
308 }
309 }
310
312 std::string handler_name_;
313
315 sparta::EventSet signal_events_;
316
318 // sparta::UniqueEvent<SchedulingPhase::PortUpdate> signal_arrive_event_ {
319 // &signal_events_, getName() + "_port_delivery_event",
320 // CREATE_SPARTA_HANDLER(SignalInPort, receiveSignal_)};
321 std::unique_ptr<PhasedUniqueEvent> user_signal_delivery_;
322 };
323
324
326 // External definitions
327
328 inline void SignalInPort::bind(Port * out)
329 {
330 SignalOutPort * outp;
331 if((outp = dynamic_cast<SignalOutPort*>(out)) == 0) {
332 throw SpartaException("ERROR: Attempt to bind to something that isn't a SignalOutPort: '" +
333 out->getName() + "' to '" + getName() + "'");
334 }
335 InPort::bind(outp);
336 }
337
338 inline void SignalOutPort::bind(Port * in)
339 {
340 SignalInPort * inp;
341 if((inp = dynamic_cast<SignalInPort *>(in)) == 0) {
342 throw SpartaException("ERROR: Attempt to bind to something that isn't a SignalInPort: '" +
343 in->getName() + "' to '" + getName() + "'");
344 }
345 OutPort::bind(in);
346 bound_in_ports_.push_back(inp);
347 }
348
349 inline void SignalOutPort::send(sparta::Clock::Cycle rel_time)
350 {
351 sparta_assert(!bound_in_ports_.empty(),
352 "ERROR! Attempt to send data on unbound port: " << getLocation());
353 for(SignalInPort* itr : bound_in_ports_) {
354 itr->send_(rel_time);
355 }
356 }
357}
358
359
360
File that defines the DataContainer class.
File that defines the EventSet class.
File that defines the Port base class.
File that defines Precedence operator>> rules between EventNode types.
#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(clname, meth)
File that defines the UniqueEvent class.
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.
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
const Clock * receiver_clock_
The receiving clock.
Definition Port.hpp:484
Base class for all OutPort types.
Definition Port.hpp:493
void bind(Port *in) override
Bind to an InPort.
Definition Port.hpp:575
A type of Event that uniquely schedules itself on the schedule within a single time quantum....
The port interface used to bind port types together and defines a port behavior.
Definition Port.hpp:59
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
A class that defines the basic scheduling interface to the Scheduler. Not intended to be used by mode...
SchedulingPhase getCurrentSchedulingPhase() const
SignalInPort receives data from sender using a SignalOutPort.
Clock::Cycle getPortDelay() const override final
Get the port delay associated with this port.
SignalInPort(const SignalInPort &)=delete
No making copies.
SignalInPort(TreeNode *portset, const std::string &name, sparta::SchedulingPhase phase, sparta::Clock::Cycle delay)
Create an SignalInPort with the given name.
void bind(Port *out) override
Bind to an SignalOutPort.
SignalInPort(TreeNode *portset, const std::string &name, sparta::Clock::Cycle delay=0)
Construct a SignalInPort with a default delivery phase based on the delay.
void setContinuing(bool continuing) override final
SignalInPort & operator=(const SignalInPort &)=delete
No assignments.
SignalOutPort is used for transferring a simple signal to another module.
SignalOutPort & operator=(const SignalOutPort &)=delete
No assignments.
SignalOutPort(TreeNode *portset, const std::string &name, bool presume_zero_delay=true)
Construct an param.
void send(sparta::Clock::Cycle rel_time=0)
Send data to bound receivers.
void bind(Port *in) override
Bind to an SignalInPort.
SignalOutPort(const SignalOutPort &)=delete
No making copies!
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.
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.