OpenASIP 2.2
Loading...
Searching...
No Matches
POMValidator.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 POMValidator.cc
26 *
27 * Implementation of POMValidator class.
28 *
29 * @author Veli-Pekka Jääskeläinen 2006 (vjaaskel-no.spam-cs.tut.fi)
30 * @note rating: red
31 */
32
33#include "POMValidator.hh"
35#include "Machine.hh"
36#include "Socket.hh"
37#include "Port.hh"
38#include "Program.hh"
39#include "Instruction.hh"
40#include "NullInstruction.hh"
41#include "Move.hh"
42#include "Terminal.hh"
43#include "Immediate.hh"
44#include "TerminalImmediate.hh"
45#include "BaseType.hh"
46#include "Operation.hh"
47#include "ContainerTools.hh"
48#include "ControlUnit.hh"
49#include "TCEString.hh"
50#include "MathTools.hh"
51#include "Conversion.hh"
52
53using namespace TTAMachine;
54using namespace TTAProgram;
55
56/**
57 * The Constructor.
58 *
59 * @param program POM to validate.
60 */
62 instructions_(program.instructionVector()) {
63
64}
65
66/**
67 * The Destructor.
68 */
71
72/**
73 * Checks the program against the target machine for given error check set.
74 *
75 * @param errorsToCheck Set of error codes which are checked.
76 * @return POMValidatorResults object contaning possible error messages.
77 */
79POMValidator::validate(const std::set<ErrorCode>& errorsToCheck) {
80
82 for (std::set<ErrorCode>::const_iterator iter = errorsToCheck.begin();
83 iter != errorsToCheck.end(); iter++) {
84 ErrorCode code = *iter;
85 if (code == CONNECTION_MISSING) {
86 checkConnectivity(*results);
87 } else if (code == LONG_IMMEDIATE_NOT_SUPPORTED) {
88 checkLongImmediates(*results);
89 } else if (code == SIMULATION_NOT_POSSIBLE) {
90 checkSimulatability(*results);
91 } else if (code == COMPILED_SIMULATION_NOT_POSSIBLE) {
93 } else {
94 assert(false);
95 }
96 }
97
98 return results;
99}
100
101
102/**
103 * Checks if the target machine has connectivity needed for program moves.
104 *
105 * @param results POMValidator results where the error messages are added.
106 */
107void
109
110 for (std::size_t instrI = 0; instrI < instructions_.size(); ++instrI) {
111 const Instruction* instruction = instructions_.at(instrI);
112 // Test all moves in the current instruction.
113 for (int i = 0; i < instruction->moveCount(); i++) {
114 const Move& move = instruction->move(i);
115
116 const Bus& bus = move.bus();
117
118 // Test move source connectivity.
119 if (move.source().isGPR() ||
120 move.source().isFUPort() ||
121 move.source().isImmediateRegister()) {
122
123 const Port& port = move.source().port();
124
125 if (port.outputSocket() == NULL) {
126 // ERROR: Source port is not connected to an output socket.
127 InstructionAddress address = instruction->address().location();
128 std::string errorMessage =
129 Conversion::toString(address) + ": " +
130 "Source port '" + port.parentUnit()->name() +
131 "." + port.name() + "' of the move on bus '" +
132 bus.name() + "' is not connected to an output socket.";
133
134 results.addError(CONNECTION_MISSING, errorMessage);
135
136 } else if (!port.outputSocket()->isConnectedTo(bus)) {
137 // ERROR: Output socket of the source port is not connected
138 // to the move bus.
139 InstructionAddress address = instruction->address().location();
140 std::string errorMessage =
141 Conversion::toString(address) + ": " +
142 "Source port '" + port.parentUnit()->name() +
143 "." + port.name() + "' of the move on bus '" +
144 bus.name() + "' is not connected to the bus.";
145 results.addError(CONNECTION_MISSING, errorMessage);
146 }
147
148 }
149
150 // Test move target connectivity.
151 if (move.destination().isGPR() ||
152 move.destination().isFUPort() ||
154
155 const Port& port = move.destination().port();
156
157 if (port.inputSocket() == NULL) {
158 // ERROR: Destination port is not connected to an output
159 // socket.
160 InstructionAddress address = instruction->address().location();
161 std::string errorMessage =
162 Conversion::toString(address) + ": " +
163 "Destination port '" + port.parentUnit()->name() +
164 "." + port.name() + "' of the move on bus '" +
165 bus.name() + "' is not connected to an input socket.";
166
167 results.addError(CONNECTION_MISSING, errorMessage);
168
169 } else if (!port.inputSocket()->isConnectedTo(bus)) {
170 // ERROR: Output socket of the target port is not connected
171 // to the move bus.
172 InstructionAddress address = instruction->address().location();
173 std::string errorMessage =
174 Conversion::toString(address) + ": " +
175 "Destination port '" + port.parentUnit()->name() +
176 "." + port.name() + "' of the move on bus '" +
177 bus.name() + "' is not connected to the bus.";
178 results.addError(CONNECTION_MISSING, errorMessage);
179 }
180
181 }
182 }
183 }
184}
185
186/**
187 * Checks long immediate assignments.
188 *
189 * @param results POMValidator results where the error messages are added.
190 */
191void
193
194 for (std::size_t instrI = 0; instrI < instructions_.size(); ++instrI) {
195 const Instruction* instruction = instructions_.at(instrI);
196
197 const InstructionTemplate& templ =
198 instruction->instructionTemplate();
199
200 std::set<std::string> destinations;
201 for (int i = 0; i < instruction->immediateCount(); i++) {
202
203 const Immediate& immediate = instruction->immediate(i);
204
205 // Check that the immediate destination terminal is an IU.
206 if (!immediate.destination().isImmediateRegister()) {
207 InstructionAddress address = instruction->address().location();
208 std::string errorMessage =
209 Conversion::toString(address) + ": " +
210 "Long immediate destination terminal is not an "
211 "immediate unit.";
212 results.addError(LONG_IMMEDIATE_NOT_SUPPORTED, errorMessage);
213 continue;
214 }
215
216 int width = immediate.value().value().width();
217 const ImmediateUnit& iu =
218 immediate.destination().immediateUnit();
219 int supportedWidth = templ.supportedWidth(iu);
220 if (width <= INT_WORD_SIZE &&
221 supportedWidth != width) {
222 // Raw magic! If the SimValue reports width higher then
223 // INT_WORD_SIZE it means immediate is floating point,
224 // and should be just respected:-)
225 // If width is less, the actuall width is recomputed
226 // based on target as if it was integer
227 // FIXME: find out how to deal with floating point
228 if (iu.extensionMode() == Machine::ZERO) {
229 // Actual required width depends on target immediate unit
231 immediate.value().value().unsignedValue());
232 }
233 if (iu.extensionMode() == Machine::SIGN) {
234 // Actual required width depends on target immediate unit
236 immediate.value().value().intValue());
237 }
238 }
239 // Check that the destination IU isn't already destination
240 // of a long immediate in the current instruction.
241 std::pair<std::set<std::string>::iterator, bool> result =
242 destinations.insert(iu.name());
243
244 if (!result.second) {
245 // Destination already in the set.
246 InstructionAddress address = instruction->address().location();
247 std::string errorMessage =
248 Conversion::toString(address) + ": " +
249 "Multiple long immediates with destination IU '" +
250 iu.name() + "'.";
251 results.addError(LONG_IMMEDIATE_NOT_SUPPORTED, errorMessage);
252 continue;
253 }
254
255 // Check that the instruction template supports long immediates
256 // with the current long immediate's width and destination IU.
257 if (supportedWidth < width) {
258 InstructionAddress address = instruction->address().location();
259 std::string errorMessage =
260 Conversion::toString(address) + ": " +
261 "Long immediate with destination IU '" +
262 iu.name() + "' has width of " +
263 Conversion::toString(width) + " bits. Instruction's " +
264 "template only supports long immediates with width of " +
266 " bits or less. For template " + templ.name();
267 results.addError(LONG_IMMEDIATE_NOT_SUPPORTED, errorMessage);
268 continue;
269 }
270 }
271 }
272}
273
274/**
275 * Checks that all operations in the program have known behaviour and
276 * can be simulated.
277 *
278 * @param results POMValidator results where the error messages are added.
279 */
280void
282
283 std::set<std::string> errOpNames;
284
285 for (std::size_t instrI = 0; instrI < instructions_.size(); ++instrI) {
286 const Instruction* instruction = instructions_.at(instrI);
287
288 for (int i = 0; i < instruction->moveCount(); i++) {
289 Move& move = instruction->move(i);
290 Terminal* destination = &move.destination();
291 if (destination->isFUPort()) {
292 if (destination->isOpcodeSetting() &&
293 !destination->operation().canBeSimulated() &&
295 errOpNames, destination->operation().name())) {
296
297 std::string opName = destination->operation().name();
298 InstructionAddress address =
299 instruction->address().location();
300
301 std::string errorMessage =
302 Conversion::toString(address) + ": " +
303 "Operation '" + opName +
304 "' cannot be simulated.";
305
306 results.addError(
307 SIMULATION_NOT_POSSIBLE, errorMessage);
308
309 errOpNames.insert(opName);
310 }
311 }
312 }
313 }
314}
315
316/**
317 * Checks for problems specific to compiled simulation only.
318 *
319 * Used to check if the program cannot be simulated with the compiled simulator.
320 *
321 * @param results POMValidator results where the error messages are added.
322 *
323 */
324void
326
327 for (std::size_t instrI = 0; instrI < instructions_.size(); ++instrI) {
328 const Instruction* instruction = instructions_.at(instrI);
329 for (int i = 0; i < instruction->moveCount(); i++) {
330 Move& move = instruction->move(i);
331 Terminal* destination = &move.destination();
332 // clocked operations
333 if (destination->isFUPort()) {
334 if (destination->isOpcodeSetting() &&
335 destination->operation().isClocked()) {
336 InstructionAddress address = instruction->address().location();
337 std::string errorMessage =
338 "Instruction at address: " +
339 Conversion::toString(address) +
340 "' cannot be simulated with the compiled simulator. "
341 "(Operation " + destination->operation().name() +
342 " is a clocked operation).";
343
345 errorMessage);
346 }
347 }
348 } // end for
349 }
350}
#define assert(condition)
const Byte INT_WORD_SIZE
Definition BaseType.hh:154
UInt32 InstructionAddress
Definition BaseType.hh:175
find Finds info of the inner loops in the program
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
static std::string toString(const T &source)
static int requiredBits(unsigned long int number)
static int requiredBitsSigned(SLongWord number)
virtual TCEString name() const
Definition Operation.cc:93
virtual bool isClocked() const
Definition Operation.cc:282
virtual bool canBeSimulated() const
Definition Operation.cc:612
void addError(POMValidator::ErrorCode code, const std::string &errorMsg)
void checkSimulatability(POMValidatorResults &results)
void checkCompiledSimulatability(POMValidatorResults &results)
ErrorCode
Error codes for different errors.
@ CONNECTION_MISSING
Connection required for a move is missing.
@ LONG_IMMEDIATE_NOT_SUPPORTED
Instruction template missing for a long immediate.
@ SIMULATION_NOT_POSSIBLE
Program contains operations with unknown behaviour.
@ COMPILED_SIMULATION_NOT_POSSIBLE
Compiled simulation is not possible.
POMValidator(const TTAProgram::Program &program)
void checkConnectivity(POMValidatorResults &results)
virtual ~POMValidator()
POMValidatorResults * validate(const std::set< ErrorCode > &errorsToCheck)
const TTAProgram::Program::InstructionVector instructions_
The program's instructions in a quickly accessed vector.
void checkLongImmediates(POMValidatorResults &results)
int intValue() const
Definition SimValue.cc:895
unsigned int unsignedValue() const
Definition SimValue.cc:919
int width() const
Definition SimValue.cc:103
virtual TCEString name() const
virtual Machine::Extension extensionMode() const
@ SIGN
Sign extension.
Definition Machine.hh:82
@ ZERO
Zero extension.
Definition Machine.hh:81
virtual Socket * outputSocket() const
Definition Port.cc:281
Unit * parentUnit() const
virtual Socket * inputSocket() const
Definition Port.cc:261
virtual std::string name() const
Definition Port.cc:141
bool isConnectedTo(const Bus &bus) const
Definition Socket.cc:331
InstructionAddress location() const
TerminalImmediate & value() const
Definition Immediate.cc:103
const Terminal & destination() const
Definition Immediate.cc:92
Move & move(int i) const
Address address() const
Immediate & immediate(int i) const
const TTAMachine::InstructionTemplate & instructionTemplate() const
Terminal & source() const
Definition Move.cc:302
Terminal & destination() const
Definition Move.cc:323
const TTAMachine::Bus & bus() const
Definition Move.cc:373
virtual SimValue value() const
virtual bool isOpcodeSetting() const
Definition Terminal.cc:285
virtual Operation & operation() const
Definition Terminal.cc:319
virtual bool isGPR() const
Definition Terminal.cc:107
virtual bool isImmediateRegister() const
Definition Terminal.cc:97
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
virtual const TTAMachine::ImmediateUnit & immediateUnit() const
Definition Terminal.cc:240
virtual bool isFUPort() const
Definition Terminal.cc:118