OpenASIP 2.2
Loading...
Searching...
No Matches
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"
45#include "FUPort.hh"
46
47#include "Application.hh"
48#include "MathTools.hh"
49
50using std::string;
51using boost::format;
52using namespace TTAMachine;
53
54const string CALL = "CALL";
55const string JUMP = "JUMP";
56
57/**
58 * The constructor.
59 *
60 * @param machine The machine to validate.
61 */
65
66
67/**
68 * The destructor.
69 */
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 */
81MachineValidator::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) {
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) {
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 */
119void
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 */
133void
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 */
154void
156 MachineValidatorResults& results) const {
157
159 for (int i = 0; i < fuNav.count(); i++) {
160 FunctionUnit* fu = fuNav.item(i);
162 }
163
164 // check GCU too
166 if (gcu != NULL) {
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 */
178void
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.";
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 */
208void
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 */
244void
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 */
270void
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.";
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.";
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 */
308void
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
361void
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}
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
const string JUMP
const string CALL
static void checkOperandBindings(const TTAMachine::FunctionUnit &fu, MachineValidatorResults &results)
void addError(MachineValidator::ErrorCode code, const std::string &errorMsg)
void checkProgramCounterPort(MachineValidatorResults &results) const
MachineValidatorResults * validate(const std::set< ErrorCode > &errorsToCheck) const
void checkGCUHasAddressSpace(MachineValidatorResults &results) const
void checkReturnAddressPort(MachineValidatorResults &results) const
void checkOperandBindings(MachineValidatorResults &results) const
void checkFUConnections(MachineValidatorResults &results) const
void checkRAPortHasSameWidthAsPCPort(MachineValidatorResults &results) const
void checkGCUExists(MachineValidatorResults &results) const
MachineValidator(const TTAMachine::Machine &machine)
ErrorCode
Error codes for different errors.
@ PC_AND_RA_PORTS_HAVE_UNEQUAL_WIDTH
RA and PC ports have unequal width.
@ IMEM_ADDR_WIDTH_DIFFERS_FROM_RA_AND_PC
Instruction memory address width differs from PC/RA port width.
@ GCU_AS_MISSING
Address space missing in GCU.
@ DIFFERENT_PORT_FOR_JUMP_AND_CALL
JUMP and CALL uses different port in GCU.
@ RA_PORT_MISSING
RA port missing in GCU.
@ FU_PORT_MISSING
FU is missing ports.
@ USED_IO_NOT_BOUND
Pipeline uses an IO which is not bound.
@ GCU_MISSING
GCU missing in machine.
@ PC_PORT_MISSING
PC port missing in GCU.
void checkIMemAddrWidth(MachineValidatorResults &results) const
void checkJumpAndCallOperandBindings(MachineValidatorResults &results) const
const TTAMachine::Machine & machine_
The machine to validate.
virtual ~MachineValidator()
static int requiredBits(unsigned long int number)
virtual ULongWord end() const
virtual int width() const
SpecialRegisterPort * returnAddressPort() const
bool hasReturnAddressPort() const
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual FUPort * operationPort(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
virtual int operationPortCount() const
virtual FUPort * port(int operand) const
ComponentType * item(int index) const
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
virtual int socketCount() const
Definition Port.cc:375