OpenASIP  2.0
SimpleOperationExecutor.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 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 SimpleOperationExecutor.cc
26  *
27  * Definition of SimpleOperationExecutor class.
28  *
29  * @author Jussi Nykänen 2004 (nykanen-no.spam-cs.tut.fi)
30  * @author Pekka Jääskeläinen 2005 (pjaaskel-no.spam-cs.tut.fi)
31  * @author Viljami Korhonen 2007 (viljami.korhonen-no.spam-tut.fi)
32  * @note rating: red
33  */
34 
36 #include "Operation.hh"
37 #include "Operand.hh"
38 #include "SequenceTools.hh"
39 #include "OperationContext.hh"
40 #include "PortState.hh"
41 #include "SimulatorToolbox.hh"
42 #include "OperationPool.hh"
43 #include "Application.hh"
44 
45 using std::vector;
46 using std::string;
47 
48 /**
49  * Constructor.
50  *
51  * @param latency Latency of the operation.
52  * @param parent Parent of the OperationExecutor.
53  */
55  int latency,
56  FUState& parent) :
57  OperationExecutor(parent), nextSlot_(0), context_(NULL),
58  pendingOperations_(0) {
59 
60  for (int i = 0; i < latency; i++) {
61  BufferCell cell;
62  buffer_.push_back(cell);
63  }
64  hasPendingOperations_ = true;
65 }
66 
67 /**
68  * Destructor.
69  */
71 }
72 
73 /**
74  * Returns the latency of the executor.
75  *
76  * @return The latency of the executor.
77  */
78 int
80  return buffer_.size();
81 }
82 
83 /**
84  * Starts new operation.
85  *
86  * First original inputs and outputs are stored. Then outputs of the operation
87  * are stored. Then operation is triggered.
88  *
89  * @param op Operation to be triggered.
90  * @todo This can be optimized a lot: try to initialize the vector as rarely
91  * as possible.
92  */
93 void
95 
96  BufferCell& nextSlot = buffer_[nextSlot_];
97 
98  const bool reuseBindings =
99  nextSlot.boundOperation_ != NULL && nextSlot.boundOperation_ == &op;
100 
101  if (!reuseBindings) {
102  const std::size_t inputOperands = op.numberOfInputs();
103  const std::size_t outputOperands = op.numberOfOutputs();
104  const std::size_t operandCount = inputOperands + outputOperands;
105 
106  assert(operandCount <= EXECUTOR_MAX_OPERAND_COUNT);
107  // let the operation access the input port values directly,
108  for (std::size_t i = 1; i <= inputOperands; ++i) {
109  /// @todo create valueConst() and value() to avoid these uglies
110  nextSlot.io_[i - 1] = &(const_cast<SimValue&>(binding(i).value()));
111  }
112 
113  // create new temporary SimValues for the outputs, assume
114  // indexing of outputs starts after inputs
115  /// @todo Fix! This should not probably be assumed, or at least
116  /// user should be notified if his operand ids are not what
117  /// are expected.
118  for (std::size_t i = inputOperands + 1; i <= operandCount; ++i) {
119  nextSlot.ioOrig_[i - 1].setBitWidth(op.operand(i).width());
120  nextSlot.io_[i - 1] = &nextSlot.ioOrig_[i - 1];
121  }
122  nextSlot.boundOperation_ = &op;
123  }
124 
125  nextSlot.operation_ = &op;
126  nextSlot.ready_ = op.simulateTrigger(nextSlot.io_, *context_);
128  hasPendingOperations_ = true;
129 }
130 
131 /**
132  * Advances clock by one cycle.
133  *
134  * Takes the oldest result in the pipeline and makes it visible in the
135  * function unit's ports.
136  */
137 void
139 
140  int index = (nextSlot_ + 1) % buffer_.size();
141 
142  BufferCell& oldestEntry = buffer_[index];
143  Operation* oldestOperation = oldestEntry.operation_;
144  if (oldestOperation != NULL) {
145 
146  const std::size_t inputOperands = oldestOperation->numberOfInputs();
147  const std::size_t outputOperands = oldestOperation->numberOfOutputs();
148  const std::size_t operandCount = inputOperands + outputOperands;
149  for (std::size_t i = inputOperands + 1; i <= operandCount; ++i) {
150  PortState& port = binding(i);
151  port.setValue(*oldestEntry.io_[i - 1]);
152  }
153  // results now moved to the FU output ports, "lifetime" of this
154  // operation execution ends in this FU
155  oldestEntry.operation_ = NULL;
158  }
159  nextSlot_++;
160  nextSlot_ = nextSlot_ % buffer_.size();
161 }
162 
163 /**
164  * Copies OperationExecutor.
165  *
166  * @return The copied OperationExecutor.
167  */
170  return new SimpleOperationExecutor(*this);
171 }
172 
173 /**
174  * Sets the OperationContext for the OperationExecutor.
175  *
176  * @param context New OperationContext.
177  */
178 void
180  context_ = &context;
181 }
182 
SimpleOperationExecutor::latency
virtual int latency() const
Definition: SimpleOperationExecutor.cc:79
SimpleOperationExecutor::BufferCell::io_
SimValue * io_[EXECUTOR_MAX_OPERAND_COUNT]
Inputs and outputs for the operation.
Definition: SimpleOperationExecutor.hh:76
SimValue::setBitWidth
void setBitWidth(int width)
Definition: SimValue.cc:113
SimpleOperationExecutor::buffer_
Buffer buffer_
Ring buffer for the pipeline slots.
Definition: SimpleOperationExecutor.hh:97
SimpleOperationExecutor::BufferCell
Definition: SimpleOperationExecutor.hh:69
SimpleOperationExecutor::advanceClock
virtual void advanceClock()
Definition: SimpleOperationExecutor.cc:138
OperationContext
Definition: OperationContext.hh:56
SimpleOperationExecutor::copy
virtual OperationExecutor * copy()
Definition: SimpleOperationExecutor.cc:169
EXECUTOR_MAX_OPERAND_COUNT
#define EXECUTOR_MAX_OPERAND_COUNT
Maximum count of operation operands supported by the executors. This is used to allocate some static ...
Definition: OperationExecutor.hh:84
SequenceTools.hh
Operand::width
virtual int width() const
Definition: Operand.cc:318
Operation::numberOfInputs
virtual int numberOfInputs() const
Definition: Operation.cc:192
SimpleOperationExecutor::BufferCell::ioOrig_
SimValue ioOrig_[EXECUTOR_MAX_OPERAND_COUNT]
Original inputs and outputs of the operation.
Definition: SimpleOperationExecutor.hh:80
SimValue
Definition: SimValue.hh:96
FUState
Definition: FUState.hh:58
assert
#define assert(condition)
Definition: Application.hh:86
RegisterState::value
virtual const SimValue & value() const
Definition: RegisterState.cc:92
SimpleOperationExecutor::SimpleOperationExecutor
SimpleOperationExecutor(int latency, FUState &parent)
Definition: SimpleOperationExecutor.cc:54
SimpleOperationExecutor::setContext
virtual void setContext(OperationContext &context)
Definition: SimpleOperationExecutor.cc:179
SimulatorToolbox.hh
OperationExecutor::hasPendingOperations_
bool hasPendingOperations_
This is set to true if the OperationExecutor is not in 'idle' mode.
Definition: OperationExecutor.hh:73
SimpleOperationExecutor::BufferCell::operation_
Operation * operation_
Operation to be executed, set to NULL when results have been moved to output ports.
Definition: SimpleOperationExecutor.hh:83
Application.hh
SimpleOperationExecutor::context_
OperationContext * context_
Operation context.
Definition: SimpleOperationExecutor.hh:99
Operation.hh
PortState
Definition: PortState.hh:51
SimpleOperationExecutor::startOperation
virtual void startOperation(Operation &op)
Definition: SimpleOperationExecutor.cc:94
OperationExecutor
Definition: OperationExecutor.hh:49
Operation
Definition: Operation.hh:59
SimpleOperationExecutor::nextSlot_
int nextSlot_
Position of the ring buffer where to put the next triggered operation.
Definition: SimpleOperationExecutor.hh:95
SimpleOperationExecutor::~SimpleOperationExecutor
virtual ~SimpleOperationExecutor()
Definition: SimpleOperationExecutor.cc:70
Operand.hh
Operation::operand
virtual Operand & operand(int id) const
Definition: Operation.cc:541
SimpleOperationExecutor::pendingOperations_
std::size_t pendingOperations_
Count of pending operations in the pipeline.
Definition: SimpleOperationExecutor.hh:101
SimpleOperationExecutor::BufferCell::boundOperation_
Operation * boundOperation_
Tells the operation for which the bindings are initialized in this "pipeline cell",...
Definition: SimpleOperationExecutor.hh:89
Operation::simulateTrigger
virtual bool simulateTrigger(SimValue **, OperationContext &context) const
Definition: Operation.cc:555
SimpleOperationExecutor::BufferCell::ready_
bool ready_
Flag telling whether results are ready or not.
Definition: SimpleOperationExecutor.hh:85
SimpleOperationExecutor.hh
OperationPool.hh
Operation::numberOfOutputs
virtual int numberOfOutputs() const
Definition: Operation.cc:202
OperationExecutor::binding
PortState & binding(int io) const
OperationContext.hh
PortState.hh
RegisterState::setValue
virtual void setValue(const SimValue &value)
Definition: RegisterState.cc:80