OpenASIP  2.0
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"
34 #include "POMValidatorResults.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 
53 using namespace TTAMachine;
54 using 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  */
70 }
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  */
79 POMValidator::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  */
107 void
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() ||
153  move.destination().isImmediateRegister()) {
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  */
191 void
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
230  width = MathTools::requiredBits(
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  */
280 void
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  */
324 void
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 }
TTAProgram::Terminal::isFUPort
virtual bool isFUPort() const
Definition: Terminal.cc:118
SimValue::intValue
int intValue() const
Definition: SimValue.cc:895
POMValidator::instructions_
const TTAProgram::Program::InstructionVector instructions_
The program's instructions in a quickly accessed vector.
Definition: POMValidator.hh:76
TTAProgram
Definition: Estimator.hh:65
TTAProgram::Immediate::value
TerminalImmediate & value() const
Definition: Immediate.cc:103
TTAProgram::Program
Definition: Program.hh:63
InstructionAddress
UInt32 InstructionAddress
Definition: BaseType.hh:175
TTAMachine::Port::inputSocket
virtual Socket * inputSocket() const
Definition: Port.cc:261
BaseType.hh
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
POMValidator::CONNECTION_MISSING
@ CONNECTION_MISSING
Connection required for a move is missing.
Definition: POMValidator.hh:55
TTAProgram::Instruction::move
Move & move(int i) const
Definition: Instruction.cc:193
POMValidatorResults
Definition: POMValidatorResults.hh:45
POMValidator::SIMULATION_NOT_POSSIBLE
@ SIMULATION_NOT_POSSIBLE
Program contains operations with unknown behaviour.
Definition: POMValidator.hh:59
POMValidator::LONG_IMMEDIATE_NOT_SUPPORTED
@ LONG_IMMEDIATE_NOT_SUPPORTED
Instruction template missing for a long immediate.
Definition: POMValidator.hh:57
TTAProgram::Instruction
Definition: Instruction.hh:57
TTAMachine::Bus
Definition: Bus.hh:53
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
POMValidator::checkLongImmediates
void checkLongImmediates(POMValidatorResults &results)
Definition: POMValidator.cc:192
TTAProgram::Move::bus
const TTAMachine::Bus & bus() const
Definition: Move.cc:373
POMValidator::checkConnectivity
void checkConnectivity(POMValidatorResults &results)
Definition: POMValidator.cc:108
Operation::isClocked
virtual bool isClocked() const
Definition: Operation.cc:282
Operation::canBeSimulated
virtual bool canBeSimulated() const
Definition: Operation.cc:612
Terminal.hh
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
Socket.hh
Conversion::toString
static std::string toString(const T &source)
POMValidatorResults.hh
TTAProgram::Terminal::operation
virtual Operation & operation() const
Definition: Terminal.cc:319
TCEString.hh
TTAMachine::InstructionTemplate
Definition: InstructionTemplate.hh:49
POMValidator::checkSimulatability
void checkSimulatability(POMValidatorResults &results)
Definition: POMValidator.cc:281
TTAProgram::Immediate::destination
const Terminal & destination() const
Definition: Immediate.cc:92
assert
#define assert(condition)
Definition: Application.hh:86
TTAProgram::TerminalImmediate::value
virtual SimValue value() const
Definition: TerminalImmediate.cc:75
Port.hh
TTAProgram::Terminal::isImmediateRegister
virtual bool isImmediateRegister() const
Definition: Terminal.cc:97
POMValidator::ErrorCode
ErrorCode
Error codes for different errors.
Definition: POMValidator.hh:53
POMValidator::COMPILED_SIMULATION_NOT_POSSIBLE
@ COMPILED_SIMULATION_NOT_POSSIBLE
Compiled simulation is not possible.
Definition: POMValidator.hh:61
TTAProgram::Immediate
Definition: Immediate.hh:54
Instruction.hh
Conversion.hh
TTAMachine::Port
Definition: Port.hh:54
NullInstruction.hh
TTAProgram::Terminal::isGPR
virtual bool isGPR() const
Definition: Terminal.cc:107
Operation.hh
TTAProgram::Terminal::immediateUnit
virtual const TTAMachine::ImmediateUnit & immediateUnit() const
Definition: Terminal.cc:240
MathTools::requiredBits
static int requiredBits(unsigned long int number)
TTAMachine::InstructionTemplate::supportedWidth
virtual int supportedWidth() const
Definition: InstructionTemplate.cc:427
TTAProgram::Address::location
InstructionAddress location() const
POMValidator::~POMValidator
virtual ~POMValidator()
Definition: POMValidator.cc:69
INT_WORD_SIZE
const Byte INT_WORD_SIZE
Definition: BaseType.hh:154
TTAProgram::Move
Definition: Move.hh:55
Machine.hh
TTAMachine::Socket::isConnectedTo
bool isConnectedTo(const Bus &bus) const
Definition: Socket.cc:331
TTAProgram::Instruction::immediate
Immediate & immediate(int i) const
Definition: Instruction.cc:285
TTAProgram::Terminal::isOpcodeSetting
virtual bool isOpcodeSetting() const
Definition: Terminal.cc:285
TTAProgram::Instruction::instructionTemplate
const TTAMachine::InstructionTemplate & instructionTemplate() const
Definition: Instruction.cc:523
SimValue::unsignedValue
unsigned int unsignedValue() const
Definition: SimValue.cc:919
SimValue::width
int width() const
Definition: SimValue.cc:103
Program.hh
TerminalImmediate.hh
Immediate.hh
TTAMachine::Port::name
virtual std::string name() const
Definition: Port.cc:141
POMValidator::POMValidator
POMValidator(const TTAProgram::Program &program)
Definition: POMValidator.cc:61
TTAProgram::Instruction::immediateCount
int immediateCount() const
Definition: Instruction.cc:267
ControlUnit.hh
TTAMachine::Port::outputSocket
virtual Socket * outputSocket() const
Definition: Port.cc:281
TTAProgram::Terminal
Definition: Terminal.hh:60
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
ContainerTools::containsValue
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
TTAProgram::Terminal::port
virtual const TTAMachine::Port & port() const
Definition: Terminal.cc:378
program
find Finds info of the inner loops in the program
Definition: InnerLoopFinder.cc:80
POMValidator::checkCompiledSimulatability
void checkCompiledSimulatability(POMValidatorResults &results)
Definition: POMValidator.cc:325
MathTools.hh
POMValidator::validate
POMValidatorResults * validate(const std::set< ErrorCode > &errorsToCheck)
Definition: POMValidator.cc:79
TTAMachine::ImmediateUnit::extensionMode
virtual Machine::Extension extensionMode() const
Definition: ImmediateUnit.cc:143
Move.hh
TTAMachine
Definition: Assembler.hh:48
MathTools::requiredBitsSigned
static int requiredBitsSigned(SLongWord number)
TTAProgram::Instruction::moveCount
int moveCount() const
Definition: Instruction.cc:176
POMValidator.hh
TTAProgram::Instruction::address
Address address() const
Definition: Instruction.cc:327
ContainerTools.hh
POMValidatorResults::addError
void addError(POMValidator::ErrorCode code, const std::string &errorMsg)
Definition: POMValidatorResults.cc:84
TTAMachine::Port::parentUnit
Unit * parentUnit() const
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50