OpenASIP  2.0
MachineValidator.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 MachineValidator.cc
26  *
27  * Implementation of MachineValidator class.
28  *
29  * @author Lasse Laasonen 2006 (lasse.laasonen-no.spam-tut.fi)
30  * @note rating: red
31  */
32 
33 #include <string>
34 #include <boost/format.hpp>
35 
36 #include "MachineValidator.hh"
38 #include "FUValidator.hh"
39 
40 #include "Machine.hh"
41 #include "ControlUnit.hh"
42 #include "HWOperation.hh"
43 #include "ExecutionPipeline.hh"
44 #include "SpecialRegisterPort.hh"
45 #include "FUPort.hh"
46 
47 #include "Application.hh"
48 #include "MathTools.hh"
49 
50 using std::string;
51 using boost::format;
52 using namespace TTAMachine;
53 
54 const string CALL = "CALL";
55 const string JUMP = "JUMP";
56 
57 /**
58  * The constructor.
59  *
60  * @param machine The machine to validate.
61  */
63  machine_(machine) {
64 }
65 
66 
67 /**
68  * The destructor.
69  */
71 }
72 
73 
74 /**
75  * Validates the machine.
76  *
77  * @param errorsToCheck Contains the error codes for the errors to check.
78  * @return Results of the validation.
79  */
81 MachineValidator::validate(const std::set<ErrorCode>& errorsToCheck) const {
82 
84  for (std::set<ErrorCode>::const_iterator iter = errorsToCheck.begin();
85  iter != errorsToCheck.end(); iter++) {
86  ErrorCode code = *iter;
87  if (code == GCU_MISSING) {
88  checkGCUExists(*results);
89  } else if (code == GCU_AS_MISSING) {
90  checkGCUHasAddressSpace(*results);
91  } else if (code == USED_IO_NOT_BOUND) {
92  checkOperandBindings(*results);
93  } else if (code == DIFFERENT_PORT_FOR_JUMP_AND_CALL) {
95  } else if (code == PC_PORT_MISSING) {
96  checkProgramCounterPort(*results);
97  } else if (code == RA_PORT_MISSING) {
98  checkReturnAddressPort(*results);
99  } else if (code == PC_AND_RA_PORTS_HAVE_UNEQUAL_WIDTH) {
101  } else if (code == IMEM_ADDR_WIDTH_DIFFERS_FROM_RA_AND_PC) {
102  checkIMemAddrWidth(*results);
103  } else if (code == FU_PORT_MISSING) {
104  checkFUConnections(*results);
105  } else {
106  assert(false);
107  }
108  }
109 
110  return results;
111 }
112 
113 
114 /**
115  * Checks that the machine has a control unit.
116  *
117  * @param results Results of the validation are added to the given instance.
118  */
119 void
121  if (machine_.controlUnit() == NULL) {
122  string errorMsg = "The machine does not have a GCU.";
123  results.addError(GCU_MISSING, errorMsg);
124  }
125 }
126 
127 
128 /**
129  * Checks that the GCU has an address space.
130  *
131  * @param results Results of the validation are added to the given instance.
132  */
133 void
135  MachineValidatorResults& results) const {
136 
138  if (gcu == NULL) {
139  return;
140  }
141  if (gcu->addressSpace() == NULL) {
142  string errorMsg = "The GCU does not have an address space.";
143  results.addError(GCU_AS_MISSING, errorMsg);
144  }
145 }
146 
147 
148 /**
149  * Checks that all the used operands of operations are bound to some port in
150  * function units.
151  *
152  * @param results Results of the validation are added to the given instance.
153  */
154 void
156  MachineValidatorResults& results) const {
157 
159  for (int i = 0; i < fuNav.count(); i++) {
160  FunctionUnit* fu = fuNav.item(i);
161  FUValidator::checkOperandBindings(*fu, results);
162  }
163 
164  // check GCU too
166  if (gcu != NULL) {
167  FUValidator::checkOperandBindings(*gcu, results);
168  }
169 }
170 
171 
172 /**
173  * Checks that the operands of JUMP and CALL operations are bound to the
174  * same port in GCU.
175  *
176  * @param results Results of the validation are added to the given instance.
177  */
178 void
180  MachineValidatorResults& results) const {
181 
183  if (gcu == NULL) {
184  return;
185  }
186 
187  if (gcu->hasOperation(CALL) && gcu->hasOperation(JUMP)) {
188  HWOperation* callOp = gcu->operation(CALL);
189  HWOperation* jumpOp = gcu->operation(JUMP);
190  FUPort* pcPort1 = callOp->port(1);
191  FUPort* pcPort2 = jumpOp->port(1);
192 
193  if (pcPort1 != NULL && pcPort2 != NULL && pcPort1 != pcPort2) {
194  string errorMsg =
195  "Operands of JUMP and CALL operations are not bound to the "
196  "same port in GCU.";
197  results.addError(DIFFERENT_PORT_FOR_JUMP_AND_CALL, errorMsg);
198  }
199  }
200 }
201 
202 
203 /**
204  * Checks that the GCU has a PC port if it has JUMP or CALL operation.
205  *
206  * @param results Results of the validation are added to the given instance.
207  */
208 void
210  MachineValidatorResults& results) const {
211 
213  if (gcu == NULL) {
214  return;
215  }
216 
217  if (gcu->hasOperation(CALL)) {
218  HWOperation* callOp = gcu->operation(CALL);
219  FUPort* pcPort = callOp->port(1);
220  if (pcPort == NULL) {
221  string errorMsg =
222  "Operand 1 of CALL operation is not bound to any port.";
223  results.addError(PC_PORT_MISSING, errorMsg);
224  }
225  }
226 
227  if (gcu->hasOperation(JUMP)) {
228  HWOperation* jumpOp = gcu->operation(JUMP);
229  FUPort* pcPort = jumpOp->port(1);
230  if (pcPort == NULL) {
231  string errorMsg =
232  "Operand 1 of JUMP operation is not bound to any port.";
233  results.addError(PC_PORT_MISSING, errorMsg);
234  }
235  }
236 }
237 
238 
239 /**
240  * Checks that the GCU has return address port if it has CALL operation.
241  *
242  * @param results Results of the validation are added to the given instance.
243  */
244 void
246  MachineValidatorResults& results) const {
247 
249  if (gcu == NULL) {
250  return;
251  }
252 
253  if (gcu->hasOperation(CALL)) {
254  if (!gcu->hasReturnAddressPort()) {
255  string errorMsg =
256  "GCU does not have return address port which is needed by "
257  "CALL operation.";
258  results.addError(RA_PORT_MISSING, errorMsg);
259  }
260  }
261 }
262 
263 
264 /**
265  * Checks that the return address port has the same width as program counter
266  * port if both exists.
267  *
268  * @param results Results of the validation are added to the given instance.
269  */
270 void
272  MachineValidatorResults& results) const {
273 
275  if (gcu == NULL) {
276  return;
277  }
278  if (!gcu->hasReturnAddressPort()) {
279  return;
280  }
281 
282  SpecialRegisterPort* raPort = gcu->returnAddressPort();
283  if (gcu->hasOperation(CALL)) {
284  FUPort* pcPort = gcu->operation(CALL)->port(1);
285  if (pcPort != NULL && pcPort->width() != raPort->width()) {
286  string errorMsg = "PC and RA ports have unequal width.";
287  results.addError(PC_AND_RA_PORTS_HAVE_UNEQUAL_WIDTH, errorMsg);
288  return;
289  }
290  }
291  if (gcu->hasOperation(JUMP)) {
292  FUPort* pcPort = gcu->operation(JUMP)->port(1);
293  if (pcPort != NULL && pcPort->width() != raPort->width()) {
294  string errorMsg = "PC and RA ports have unequal width.";
295  results.addError(PC_AND_RA_PORTS_HAVE_UNEQUAL_WIDTH, errorMsg);
296  return;
297  }
298  }
299 }
300 
301 
302 /**
303  * Checks that the address width of instruction memory is the same as PC and
304  * RA port width.
305  *
306  * @param results Results of the validation are added to the given instance.
307  */
308 void
310  MachineValidatorResults& results) const {
311 
313  if (gcu == NULL) {
314  return;
315  }
316 
317  AddressSpace* imem = gcu->addressSpace();
318  if (imem == NULL) {
319  return;
320  }
321 
322  int addrWidth = MathTools::requiredBits(imem->end());
323 
324  if (gcu->hasReturnAddressPort()) {
325  SpecialRegisterPort* raPort = gcu->returnAddressPort();
326  if (raPort->width() != addrWidth) {
327  string errorMsg =
328  "Return address port has different width than "
329  "instruction memory address.";
330  results.addError(
332  }
333  } else {
334  FUPort* pcPort = NULL;
335  if (gcu->hasOperation(JUMP)) {
336  HWOperation* jumpOp = gcu->operation(JUMP);
337  pcPort = jumpOp->port(1);
338  }
339  if (pcPort == NULL && gcu->hasOperation(CALL)) {
340  HWOperation* callOp = gcu->operation(CALL);
341  pcPort = callOp->port(1);
342  }
343 
344  if (pcPort != NULL && pcPort->width() != addrWidth) {
345  string errorMsg =
346  "Program counter port has different width than instruction "
347  "memory address.";
348  results.addError(
350  }
351  }
352 }
353 
354 /**
355  * Checks that the every FU has all the input and output ports that it needs.
356  *
357  *
358  * @param results Results of the validation are added to the given instance.
359  */
360 
361 void
363  const Machine::FunctionUnitNavigator fuNav =
365 
366  for (int i = 0; i < fuNav.count(); i++) {
367  FunctionUnit& fu = *fuNav.item(i);
368  for (int p = 0; p < fu.operationPortCount(); p++) {
369  FUPort& port = *fu.operationPort(p);
370  if (port.socketCount() == 0) {
371  string errorMsg = "The machine has an FU with missing ports.";
372  results.addError(FU_PORT_MISSING, errorMsg);
373  }
374  }
375  }
376 }
FUValidator::checkOperandBindings
static void checkOperandBindings(const TTAMachine::FunctionUnit &fu, MachineValidatorResults &results)
Definition: FUValidator.cc:54
MachineValidator::checkGCUHasAddressSpace
void checkGCUHasAddressSpace(MachineValidatorResults &results) const
Definition: MachineValidator.cc:134
MachineValidator::IMEM_ADDR_WIDTH_DIFFERS_FROM_RA_AND_PC
@ IMEM_ADDR_WIDTH_DIFFERS_FROM_RA_AND_PC
Instruction memory address width differs from PC/RA port width.
Definition: MachineValidator.hh:71
machine
TTAMachine::Machine * machine
the architecture definition of the estimated processor
Definition: EstimatorCmdLineUI.cc:59
MachineValidator::GCU_MISSING
@ GCU_MISSING
GCU missing in machine.
Definition: MachineValidator.hh:57
TTAMachine::HWOperation
Definition: HWOperation.hh:52
TTAMachine::AddressSpace
Definition: AddressSpace.hh:51
CALL
const string CALL
Definition: MachineValidator.cc:54
ExecutionPipeline.hh
MachineValidator.hh
MachineValidator::machine_
const TTAMachine::Machine & machine_
The machine to validate.
Definition: MachineValidator.hh:98
MachineValidator::USED_IO_NOT_BOUND
@ USED_IO_NOT_BOUND
Pipeline uses an IO which is not bound.
Definition: MachineValidator.hh:61
MachineValidatorResults.hh
TTAMachine::FunctionUnit::addressSpace
virtual AddressSpace * addressSpace() const
Definition: FunctionUnit.cc:580
MachineValidator::MachineValidator
MachineValidator(const TTAMachine::Machine &machine)
Definition: MachineValidator.cc:62
TTAMachine::Machine::Navigator::count
int count() const
MachineValidator::PC_PORT_MISSING
@ PC_PORT_MISSING
PC port missing in GCU.
Definition: MachineValidator.hh:65
MachineValidator::checkIMemAddrWidth
void checkIMemAddrWidth(MachineValidatorResults &results) const
Definition: MachineValidator.cc:309
MachineValidatorResults
Definition: MachineValidatorResults.hh:45
TTAMachine::Port::socketCount
virtual int socketCount() const
Definition: Port.cc:375
assert
#define assert(condition)
Definition: Application.hh:86
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
TTAMachine::HWOperation::port
virtual FUPort * port(int operand) const
Definition: HWOperation.cc:320
TTAMachine::FUPort
Definition: FUPort.hh:46
MachineValidator::FU_PORT_MISSING
@ FU_PORT_MISSING
FU is missing ports.
Definition: MachineValidator.hh:75
TTAMachine::Machine::controlUnit
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:345
MachineValidator::GCU_AS_MISSING
@ GCU_AS_MISSING
Address space missing in GCU.
Definition: MachineValidator.hh:59
HWOperation.hh
TTAMachine::SpecialRegisterPort
Definition: SpecialRegisterPort.hh:48
MachineValidator::PC_AND_RA_PORTS_HAVE_UNEQUAL_WIDTH
@ PC_AND_RA_PORTS_HAVE_UNEQUAL_WIDTH
RA and PC ports have unequal width.
Definition: MachineValidator.hh:69
MachineValidator::checkRAPortHasSameWidthAsPCPort
void checkRAPortHasSameWidthAsPCPort(MachineValidatorResults &results) const
Definition: MachineValidator.cc:271
TTAMachine::ControlUnit
Definition: ControlUnit.hh:50
Application.hh
JUMP
const string JUMP
Definition: MachineValidator.cc:55
MachineValidator::DIFFERENT_PORT_FOR_JUMP_AND_CALL
@ DIFFERENT_PORT_FOR_JUMP_AND_CALL
JUMP and CALL uses different port in GCU.
Definition: MachineValidator.hh:63
TTAMachine::Machine::functionUnitNavigator
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition: Machine.cc:380
MachineValidatorResults::addError
void addError(MachineValidator::ErrorCode code, const std::string &errorMsg)
Definition: MachineValidatorResults.cc:85
MachineValidator::ErrorCode
ErrorCode
Error codes for different errors.
Definition: MachineValidator.hh:55
MathTools::requiredBits
static int requiredBits(unsigned long int number)
MachineValidator::checkReturnAddressPort
void checkReturnAddressPort(MachineValidatorResults &results) const
Definition: MachineValidator.cc:245
TTAMachine::FunctionUnit::hasOperation
virtual bool hasOperation(const std::string &name) const
Definition: FunctionUnit.cc:330
Machine.hh
MachineValidator::checkGCUExists
void checkGCUExists(MachineValidatorResults &results) const
Definition: MachineValidator.cc:120
TTAMachine::FunctionUnit::operationPortCount
virtual int operationPortCount() const
Definition: FunctionUnit.cc:182
MachineValidator::RA_PORT_MISSING
@ RA_PORT_MISSING
RA port missing in GCU.
Definition: MachineValidator.hh:67
MachineValidator::validate
MachineValidatorResults * validate(const std::set< ErrorCode > &errorsToCheck) const
Definition: MachineValidator.cc:81
FUPort.hh
ControlUnit.hh
SpecialRegisterPort.hh
MachineValidator::checkProgramCounterPort
void checkProgramCounterPort(MachineValidatorResults &results) const
Definition: MachineValidator.cc:209
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
FUValidator.hh
TTAMachine::FunctionUnit::operation
virtual HWOperation * operation(const std::string &name) const
Definition: FunctionUnit.cc:363
MachineValidator::~MachineValidator
virtual ~MachineValidator()
Definition: MachineValidator.cc:70
MathTools.hh
TTAMachine::FunctionUnit::operationPort
virtual FUPort * operationPort(const std::string &name) const
Definition: FunctionUnit.cc:224
TTAMachine
Definition: Assembler.hh:48
TTAMachine::ControlUnit::returnAddressPort
SpecialRegisterPort * returnAddressPort() const
Definition: ControlUnit.cc:307
MachineValidator::checkJumpAndCallOperandBindings
void checkJumpAndCallOperandBindings(MachineValidatorResults &results) const
Definition: MachineValidator.cc:179
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
TTAMachine::AddressSpace::end
virtual ULongWord end() const
Definition: AddressSpace.cc:177
TTAMachine::ControlUnit::hasReturnAddressPort
bool hasReturnAddressPort() const
Definition: ControlUnit.cc:295
TTAMachine::BaseFUPort::width
virtual int width() const
Definition: BaseFUPort.cc:109
MachineValidator::checkOperandBindings
void checkOperandBindings(MachineValidatorResults &results) const
Definition: MachineValidator.cc:155
TTAMachine::Machine
Definition: Machine.hh:73
MachineValidator::checkFUConnections
void checkFUConnections(MachineValidatorResults &results) const
Definition: MachineValidator.cc:362