OpenASIP 2.2
Loading...
Searching...
No Matches
FUState.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2017 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file FUState.cc
26 *
27 * Definition of FUState class.
28 *
29 * @author Jussi Nykänen 2004 (nykanen-no.spam-cs.tut.fi)
30 * @author Pekka Jääskeläinen 2005,2010,2017 (pjaaskel-no.spam-cs.tut.fi)
31 * @note rating: red
32 */
33
34#include "FUState.hh"
35#include "Operation.hh"
36#include "OperationExecutor.hh"
39#include "InputPortState.hh"
42#include "PortState.hh"
43#include "Application.hh"
44#include "OperationContext.hh"
45#include "OutputPortState.hh"
46#include "OperationContext.hh"
47#include "SimulatorToolbox.hh"
48#include "OperationPool.hh"
49#include "Application.hh"
50#include "SequenceTools.hh"
51#include "Conversion.hh"
54
55using std::vector;
56using std::string;
57
58//////////////////////////////////////////////////////////////////////////////
59// FUState
60//////////////////////////////////////////////////////////////////////////////
61
62/**
63 * Constructor (no explicitly given FU name).
64 *
65 * @param lock Global lock signal.
66 */
68 ClockedState(), idle_(false), trigger_(false),
69 nextOperation_(NULL), nextExecutor_(NULL),
70 operationContext_(DEFAULT_FU_NAME),
71 activeExecutors_(0), detailedModel_(NULL) {
72}
73
74/**
75 * Constructor (with explicitly given FU name).
76 *
77 * @param lock Global lock signal.
78 */
80 ClockedState(), idle_(false), trigger_(false),
81 nextOperation_(NULL), nextExecutor_(NULL), operationContext_(name),
82 activeExecutors_(0), detailedModel_(NULL) {
83}
84
85/**
86 * Destructor.
87 */
92
93/**
94 * Clears input and output ports.
95 */
96void
98 inputPorts_.clear();
99 outputPorts_.clear();
100}
101
102void
104 for (ExecutorContainer::iterator i = executors_.begin();
105 i != executors_.end(); ++i) {
106 Operation* op = (*i).first;
107 // Ensure the init state is called again.
108 op->deleteState(context());
109 op->createState(context());
110 // Reset the internal state of executor
111 (*i).second->reset();
112 }
113}
114
115/**
116 * Handles actions that take place in the end of the clock cycle.
117 *
118 * If operation is triggered, startOperation() of the executor of the
119 * operation is called.
120 */
121void
123 if (trigger_) {
124 if (nextOperation_ == NULL) {
125 throw Exception(
126 __FILE__, __LINE__, __func__,
127 "Tried to trigger FU without operation code.");
128 }
129 if (nextExecutor_ == NULL) {
130 ExecutorContainer::iterator iter = executors_.find(nextOperation_);
131 assert(iter != executors_.end());
132 nextExecutor_ = (*iter).second;
133 }
134 // set this flag to false before actually handling the trigger
135 // condition because startOperation() can cause a runtime error
136 // exception
137 trigger_ = false;
141 idle_ = false;
142 }
143 }
144}
145
146/**
147 * Handles actions that take place while clock cycle changes.
148 *
149 * advanceClock() of all active operation executors are called.
150 */
151void
153
154 if (detailedModel_ != NULL)
156
157 // in case there are no active operations and there are no states
158 // which need clock advancing, the FU is in idle state
159 if (activeExecutors_ == 0 && context().isEmpty()) {
160 idle_ = true;
161 return;
162 } else if (activeExecutors_ == 1 && nextExecutor_ != NULL &&
164 // a special case for sequential simulation:
165 // if there's only one active executor, and it's the one
166 // triggered previously in endClock(), we can use
167 // nextExecutor_ and avoid traversing the whole list of executors
171 idle_ = false;
172 } else {
174 idle_ = true;
175 }
176 // advance clock of all operations with state
177 /// @todo detect if there are *clocked* state objects
178 if (!context().isEmpty()) {
180 }
181 return;
182 }
183
185 size_t execListSize = execList_.size();
186 for (size_t i = 0; i < execListSize; ++i) {
187 OperationExecutor* opexec = execList_[i];
188 if (opexec->hasPendingOperations()) {
189 opexec->advanceClock();
190 // check if it's still active
191 if (opexec->hasPendingOperations()) {
193 }
194 }
195 }
196 // advance clock of all operations with state
197 /// @todo detect if there are *clocked* state objects
198 if (!context().isEmpty()) {
200 }
201
202 idle_ = (activeExecutors_ == 0 && context().isEmpty());
203}
204
205/**
206 * Adds new input port state.
207 *
208 * @param port New input port state.
209 */
210void
212 inputPorts_.push_back(&port);
213}
214
215/**
216 * Adds new output port state.
217 *
218 * @param port New output port state.
219 */
220void
222 outputPorts_.push_back(&port);
223}
224
225/**
226 * Adds operation executor for a given operation.
227 *
228 * @param opExec Operation executor to be added.
229 * @param op Operation which executor is added.
230 */
231void
233
234 op.createState(context());
235
236 // do not use same operation executor even if the latency and operand
237 // bindings are equal between the operations, because the executor
238 // properties can be different (especially, one of the executors can
239 // have conflict detection)
240 OperationExecutor* newExecutor = opExec.copy();
241 execList_.push_back(newExecutor);
242 newExecutor->setContext(context());
243 executors_[&op] = newExecutor;
244}
245
246/**
247 * Replaces the operation executor model for an operation.
248 *
249 * Does not copy the operation executor but uses the given instance.
250 * The method copies the I/O bindings and sets the parent FUState from
251 * the old model.
252 *
253 * @param op Operation of which executor is added.
254 * @param newExecutor Operation executor to be set.
255 */
256void
258 Operation& op,
259 OperationExecutor* newExecutor) {
260
261 op.createState(context());
262 newExecutor->setContext(context());
263
264 OperationExecutor* oldExecutor = executors_[&op];
265 newExecutor->setParent(oldExecutor->parent());
266
267 /* Copy the operand-port bindings. */
268 for (int ioId = 1;
269 ioId <= op.numberOfInputs() + op.numberOfOutputs(); ++ioId) {
270 newExecutor->addBinding(ioId, oldExecutor->binding(ioId));
271 }
272 assert(sameBindings(*oldExecutor, *newExecutor, op));
273
274 /* Replace the executor in the execution list. */
275 for (std::size_t i = 0; i < execList_.size(); ++i) {
276 if (execList_.at(i) == oldExecutor) {
277 execList_[i] = newExecutor;
278 break;
279 }
280 }
281 executors_[&op] = newExecutor;
282 delete oldExecutor;
283}
284
285/**
286 * Sets a detailed operation simulation model for all operations in
287 * the FU.
288 */
289void
291 Operation& op,
293
295 dynamic_cast<MultiLatencyOperationExecutor*>(executor(op));
296 assert (oe != NULL && "Can only add details to a complex executor.");
297 oe->setOperationSimulator(sim);
298}
299
300/**
301 * Sets a detailed operation simulation model for all operations in the FU.
302 */
303void
305
306 for (ExecutorContainer::iterator i = executors_.begin();
307 i != executors_.end(); ++i) {
308 Operation* op = (*i).first;
309 setOperationSimulator(*op, sim);
310 }
311 detailedModel_ = &sim;
312}
313
314
315/**
316 * Returns true if the two OperationExecutors have the same bindings.
317 *
318 * @param exec1 First OperationExecutor.
319 * @param exec2 Second OperationExecutor.
320 * @param op Operation to be executed with executors.
321 * @return True if the two executors have same bindings.
322 */
323bool
325 OperationExecutor& exec1,
326 OperationExecutor& exec2,
327 Operation& op) {
328
329 for (int i = 1; i <= op.numberOfInputs() + op.numberOfOutputs(); i++) {
330
331 PortState* port1 = NULL;
332 try {
333 port1 = &exec1.binding(i);
334 } catch (const OutOfRange& o) {
335 return false;
336 }
337
338 PortState* port2 = NULL;
339 try {
340 port2 = &exec2.binding(i);
341 } catch (const OutOfRange& o) {
342 return false;
343 }
344
345 if (port1 != port2) {
346 return false;
347 }
348 }
349 return true;
350}
351
352/**
353 * Returns OperationExecutor for the given operation.
354 *
355 * @param op The operation of the wanted OperationExecutor.
356 */
359 ExecutorContainer::iterator iter = executors_.find(&op);
360 if (iter == executors_.end()) {
361 return NULL;
362 } else {
363 return (*iter).second;
364 }
365}
366
367/**
368 * Returns the operation context.
369 *
370 * This is a "template method" to allow differently initialized
371 * OperationContext-classes in FUState subclasses.
372 *
373 * @return The operation context for the FU.
374 */
379
380//////////////////////////////////////////////////////////////////////////////
381// NullFUState
382//////////////////////////////////////////////////////////////////////////////
383
385
386/**
387 * Returns the instance of NullFUState.
388 *
389 * @return Instance of NullFUState.
390 */
393 return instance_;
394}
395
396/**
397 * Constructor.
398 */
401
402/**
403 * Destructor.
404 */
407
408/**
409 * Aborts the program with error message.
410 */
411void
413 Application::abortWithError("endClock()");
414}
415
416/**
417 * Aborts the program with error message.
418 */
419void
421 Application::abortWithError("advanceClock()");
422}
423
424/**
425 * Aborts the program with error message.
426 */
427void
429 Application::abortWithError("addInputPortState()");
430}
431
432/**
433 * Aborts the program with error message.
434 */
435void
437 Application::abortWithError("addOutputPortState()");
438}
439
440/**
441 * Aborts the program with error message.
442 */
443void
445 Application::abortWithError("addOperationExecutor()");
446}
447
448/**
449 * Aborts the program with error message.
450 *
451 * @return Never returns.
452 */
455 Application::abortWithError("executor()");
456 return NULL;
457}
458
#define __func__
#define assert(condition)
find Finds info of the inner loops in the false
#define DEFAULT_FU_NAME
bool trigger_
True if operation is triggered in current clock cycle.
Definition FUState.hh:119
virtual OperationContext & context()
Definition FUState.cc:376
OperationContext operationContext_
The operation context for this FU.
Definition FUState.hh:125
std::size_t activeExecutors_
Count of active executors (to allow returning instantly from advanceClock())
Definition FUState.hh:136
bool idle_
The idle status of the FU. The derived classes should alway set this to true when possible to avoid u...
Definition FUState.hh:95
Operation * nextOperation_
Operation to be triggered next.
Definition FUState.hh:121
virtual void replaceOperationExecutor(Operation &op, OperationExecutor *newExecutor)
Definition FUState.cc:257
virtual void addOutputPortState(PortState &port)
Definition FUState.cc:221
FUState()
Definition FUState.cc:67
virtual void advanceClock()
Definition FUState.cc:152
OperationExecutor * nextExecutor_
OperationExecutor to be used for the next operation (an optimization).
Definition FUState.hh:123
virtual void reset()
this is called at (re)initialization of the simulation
Definition FUState.cc:103
bool sameBindings(OperationExecutor &exec1, OperationExecutor &exec2, Operation &op)
Definition FUState.cc:324
virtual void addInputPortState(PortState &port)
Definition FUState.cc:211
virtual void addOperationExecutor(OperationExecutor &opExec, Operation &op)
Definition FUState.cc:232
ExecutorList execList_
All the different instances of OperationExecutors.
Definition FUState.hh:129
std::vector< PortState * > inputPorts_
Input ports of the function unit.
Definition FUState.hh:131
virtual OperationExecutor * executor(Operation &op)
Definition FUState.cc:358
void clearPorts()
Definition FUState.cc:97
virtual void endClock()
Definition FUState.cc:122
ExecutorContainer executors_
All operation executors.
Definition FUState.hh:127
DetailedOperationSimulator * detailedModel_
Optional detailed operation simulation model. Assume there's one such model per FU or none at all for...
Definition FUState.hh:140
virtual void setOperationSimulator(DetailedOperationSimulator &sim)
Definition FUState.cc:304
virtual ~FUState()
Definition FUState.cc:88
std::vector< PortState * > outputPorts_
Output ports of the function unit.
Definition FUState.hh:133
virtual void setOperationSimulator(DetailedOperationSimulator &sim)
virtual void addInputPortState(PortState &port)
Definition FUState.cc:428
virtual ~NullFUState()
Definition FUState.cc:405
virtual void addOutputPortState(PortState &port)
Definition FUState.cc:436
static NullFUState instance_
Unique instance of NullFUState.
Definition FUState.hh:177
virtual void addOperationExecutor(OperationExecutor &opExec, Operation &op)
Definition FUState.cc:444
virtual void advanceClock()
Definition FUState.cc:420
virtual void endClock()
Definition FUState.cc:412
virtual OperationExecutor * executor(Operation &op)
Definition FUState.cc:454
static NullFUState & instance()
Definition FUState.cc:392
void addBinding(int io, PortState &port)
PortState & binding(int io) const
bool hasPendingOperations() const
virtual void advanceClock()=0
virtual void setContext(OperationContext &context)=0
void setParent(FUState &parent)
virtual void startOperation(Operation &op)=0
FUState & parent() const
virtual OperationExecutor * copy()=0
virtual void deleteState(OperationContext &context) const
Definition Operation.cc:601
virtual void createState(OperationContext &context) const
Definition Operation.cc:590
virtual int numberOfInputs() const
Definition Operation.cc:192
virtual int numberOfOutputs() const
Definition Operation.cc:202
static void deleteAllItems(SequenceType &aSequence)