00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "fennel/common/CommonPreamble.h"
00023 #include "fennel/calculator/Calculator.h"
00024 #include "fennel/calculator/Instruction.h"
00025 #include "fennel/calculator/CalcAssembler.h"
00026
00027 #include "boost/format.hpp"
00028 using boost::format;
00029
00030 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/calculator/Calculator.cpp#2 $");
00031
00032 Calculator::Calculator(DynamicParamManager* dynamicParamManager) :
00033 mIsUsingAssembler(true),
00034 mIsAssembling(false),
00035 mPDynamicParamManager(dynamicParamManager)
00036 {
00037 init(0,0,0,0,0,0);
00038 }
00039
00040
00041 Calculator::Calculator(
00042 DynamicParamManager* dynamicParamManager,
00043 int codeSize, int literalSize, int inputSize,
00044 int outputSize, int localSize, int statusSize) :
00045 mIsUsingAssembler(false),
00046 mIsAssembling(false),
00047 mPDynamicParamManager(dynamicParamManager)
00048 {
00049 init(
00050 codeSize, literalSize, inputSize, outputSize,
00051 localSize, statusSize);
00052 }
00053
00054 void
00055 Calculator::init(
00056 int codeSize, int literalSize, int inputSize,
00057 int outputSize, int localSize, int statusSize)
00058 {
00059 mCode.reserve(codeSize);
00060 mRegisterRef[RegisterReference::ELiteral].reserve(literalSize);
00061 mRegisterRef[RegisterReference::EInput].reserve(inputSize);
00062 mRegisterRef[RegisterReference::EOutput].reserve(outputSize);
00063 mRegisterRef[RegisterReference::ELocal].reserve(localSize);
00064 mRegisterRef[RegisterReference::EStatus].reserve(statusSize);
00065
00066 int i;
00067 for (i = RegisterReference::EFirstSet;
00068 i < RegisterReference::ELastSet;
00069 i++) {
00070
00071
00072 mRegisterSetBinding[i] = NULL;
00073
00074 mRegisterSetDescriptor[i] = NULL;
00075 }
00076
00077 mOutputRegisterByReference = true;
00078
00079
00080 mContinueOnException = true;
00081 }
00082
00083 Calculator::~Calculator()
00084 {
00085 uint i;
00086 for (i = RegisterReference::EFirstSet;
00087 i < RegisterReference::ELastSet;
00088 i++) {
00089 unbind((RegisterReference::ERegisterSet)i);
00090 }
00091
00092 if (mIsUsingAssembler) {
00093
00094 for (i = RegisterReference::EFirstSet;
00095 i < RegisterReference::ELastSet;
00096 i++) {
00097 for (uint reg = 0; reg < mRegisterRef[i].size(); reg++) {
00098 if (mRegisterRef[i][reg]) {
00099 delete mRegisterRef[i][reg];
00100 }
00101 }
00102 mRegisterRef[i].clear();
00103 mRegisterReset.clear();
00104 }
00105
00106
00107
00108 for (i = 0; i < mCode.size(); i++) {
00109 delete mCode[i];
00110 }
00111 mCode.clear();
00112
00113 for (i = 0; i < mBuffers.size(); i++) {
00114 delete[] mBuffers[i];
00115 }
00116 mBuffers.clear();
00117 }
00118 }
00119
00120 void
00121 Calculator::outputRegisterByReference(bool flag)
00122 {
00123 mOutputRegisterByReference = flag;
00124 }
00125
00126 void
00127 Calculator::assemble(const char *program)
00128 {
00129 assert(mIsUsingAssembler);
00130
00131 FENNEL_TRACE(
00132 TRACE_FINEST,
00133 "Calculator instructions:" << endl <<
00134 InstructionFactory::signatures());
00135 FENNEL_TRACE(
00136 TRACE_FINEST,
00137 "Calculator extended instructions:" << endl <<
00138 InstructionFactory::extendedSignatures());
00139 FENNEL_TRACE(
00140 TRACE_FINE,
00141 "Calculator assembly = |" << endl
00142 << program << "|" << endl);
00143
00144 mIsAssembling = true;
00145 CalcAssembler assembler(this);
00146 assembler.assemble(program);
00147 mIsAssembling = false;
00148 }
00149
00150 void Calculator::unbind(
00151 RegisterReference::ERegisterSet regset,
00152 bool unbindDescriptor)
00153 {
00154 if (unbindDescriptor && mRegisterSetDescriptor[regset]) {
00155 delete mRegisterSetDescriptor[regset];
00156 mRegisterSetDescriptor[regset] = NULL;
00157 }
00158 if (mRegisterSetBinding[regset]) {
00159 delete mRegisterSetBinding[regset];
00160 mRegisterSetBinding[regset] = NULL;
00161 }
00162 }
00163
00164 void Calculator::bind(
00165 RegisterReference::ERegisterSet regset,
00166 TupleData* data,
00167 const TupleDescriptor& desc)
00168 {
00169 assert(mIsUsingAssembler ? mIsAssembling : true);
00170 assert(regset < RegisterReference::ELastSet);
00171 assert(data);
00172
00173
00174
00175
00176
00177
00178 assert((regset == RegisterReference::ELiteral) ?
00179 !mRegisterSetBinding[RegisterReference::ELiteral] : true);
00180 assert((regset == RegisterReference::ELocal) ?
00181 !mRegisterSetBinding[RegisterReference::ELocal] : true);
00182
00183 unbind(regset);
00184 mRegisterSetBinding[regset] = new RegisterSetBinding(data);
00185 mRegisterSetDescriptor[regset] = new TupleDescriptor(desc);
00186
00187
00188 if (regset == RegisterReference::ELiteral ||
00189 regset == RegisterReference::ELocal) {
00190 for_each(
00191 mRegisterRef[regset].begin(),
00192 mRegisterRef[regset].end(),
00193 mem_fun(&RegisterReference::cachePointer));
00194 }
00195
00196
00197
00198
00199 size_t totalResetableRegisters =
00200 mRegisterRef[RegisterReference::ELiteral].size() +
00201 mRegisterRef[RegisterReference::ELocal].size();
00202 mRegisterReset.reserve(totalResetableRegisters);
00203 }
00204
00205 void Calculator::bind(
00206 TupleData* input, TupleData* output,
00207 bool takeOwnwership, const TupleData* outputWrite)
00208 {
00209 unbind(RegisterReference::EInput, false);
00210 mRegisterSetBinding[RegisterReference::EInput] =
00211 new RegisterSetBinding(input, takeOwnwership);
00212 unbind(RegisterReference::EOutput, false);
00213 if (outputWrite) {
00214 mRegisterSetBinding[RegisterReference::EOutput] =
00215 new RegisterSetBinding(output, outputWrite, takeOwnwership);
00216 } else {
00217 mRegisterSetBinding[RegisterReference::EOutput] =
00218 new RegisterSetBinding(output, takeOwnwership);
00219 }
00220 }
00221
00222 TupleDescriptor
00223 Calculator::getOutputRegisterDescriptor() const
00224 {
00225 return *(mRegisterSetDescriptor[RegisterReference::EOutput]);
00226 }
00227
00228 TupleDescriptor
00229 Calculator::getInputRegisterDescriptor() const
00230 {
00231 return *(mRegisterSetDescriptor[RegisterReference::EInput]);
00232 }
00233
00234 TupleDescriptor
00235 Calculator::getStatusRegisterDescriptor() const
00236 {
00237 return *(mRegisterSetDescriptor[RegisterReference::EStatus]);
00238 }
00239
00240 TupleData const * const
00241 Calculator::getStatusRegister() const
00242 {
00243 return &(mRegisterSetBinding[RegisterReference::EStatus]->asTupleData());
00244 }
00245
00246 void Calculator::zeroStatusRegister()
00247 {
00248 if (mRegisterSetDescriptor[RegisterReference::EStatus] != NULL) {
00249 RegisterSetBinding *statusBinding =
00250 mRegisterSetBinding[RegisterReference::EStatus];
00251
00252 int ncols = statusBinding->asTupleData().size();
00253
00254 for (int i = 0; i < ncols; i++) {
00255 memset(
00256 const_cast<PBuffer>((*statusBinding)[i].pData),
00257 0,
00258 (*statusBinding)[i].cbData);
00259 }
00260 }
00261 }
00262
00263 void
00264 Calculator::continueOnException(bool c)
00265 {
00266 mContinueOnException = c;
00267 }
00268
00269
00270 void
00271 Calculator::exec()
00272 {
00273
00274 mWarnings.clear();
00275
00276
00277 for_each(
00278 mRegisterReset.begin(),
00279 mRegisterReset.end(),
00280 mem_fun(&RegisterReference::cachePointer));
00281 mRegisterReset.clear();
00282
00283 #ifdef DEBUG
00284 ostringstream oss;
00285 TuplePrinter p;
00286 if (isTracingLevel(TRACE_FINEST)) {
00287 oss << "Pre-Exec" << endl << "Output Register: " << endl;
00288 p.print(
00289 oss, getOutputRegisterDescriptor(),
00290 mRegisterSetBinding[RegisterReference::EOutput]->asTupleData());
00291 oss << endl << "Input Register: " << endl;
00292 p.print(
00293 oss, getInputRegisterDescriptor(),
00294 mRegisterSetBinding[RegisterReference::EInput]->asTupleData());
00295 oss << endl << "Status Register: " << endl;
00296 p.print(
00297 oss, getStatusRegisterDescriptor(),
00298 mRegisterSetBinding[RegisterReference::EStatus]->asTupleData());
00299 oss << endl;
00300 trace(TRACE_FINEST, oss.str());
00301 }
00302 #endif
00303
00304
00305 TProgramCounter pc = 0, endOfProgram;
00306 endOfProgram = mCode.size();
00307
00308 while (pc >= 0 && pc < endOfProgram) {
00309 try {
00310 #ifdef DEBUG
00311 int oldpc = pc;
00312 string out;
00313 if (isTracingLevel(TRACE_FINEST)) {
00314 mCode[oldpc]->describe(out, true);
00315 FENNEL_TRACE(
00316 TRACE_FINEST, "BF [" << oldpc << "] " << out.c_str());
00317 }
00318 #endif
00319
00320 mCode[pc]->exec(pc);
00321
00322 #ifdef DEBUG
00323 if (isTracingLevel(TRACE_FINEST)) {
00324 mCode[oldpc]->describe(out, true);
00325 FENNEL_TRACE(
00326 TRACE_FINEST, "AF [" << oldpc << "] " << out.c_str());
00327 }
00328 #endif
00329 } catch (CalcMessage m) {
00330
00331 mWarnings.push_back(m);
00332 if (!mContinueOnException) {
00333 break;
00334 }
00335 }
00336 }
00337 #ifdef DEBUG
00338 if (isTracingLevel(TRACE_FINEST)) {
00339 oss.clear();
00340 oss << "Post-Exec" << endl << "Output Register: " << endl;
00341 p.print(
00342 oss, getOutputRegisterDescriptor(),
00343 mRegisterSetBinding[RegisterReference::EOutput]->asTupleData());
00344 oss << endl << "Input Register: " << endl;
00345 p.print(
00346 oss, getInputRegisterDescriptor(),
00347 mRegisterSetBinding[RegisterReference::EInput]->asTupleData());
00348 oss << endl << "Status Register: " << endl;
00349 p.print(
00350 oss, getStatusRegisterDescriptor(),
00351 mRegisterSetBinding[RegisterReference::EStatus]->asTupleData());
00352 oss << endl << "Warnings: |" << warnings() << "|"<< endl;
00353 trace(TRACE_FINEST, oss.str());
00354 }
00355 #endif
00356 }
00357
00358 string
00359 Calculator::warnings()
00360 {
00361 string ret;
00362 deque<CalcMessage>::iterator iter = mWarnings.begin(),
00363 end = mWarnings.end();
00364 int i = 0;
00365
00366 while (iter != end) {
00367 ret += boost::io::str(format("[%d]:PC=%ld Code=") % i % iter->pc);
00368 ret += iter->str;
00369 ret += " ";
00370 iter++;
00371 i++;
00372 }
00373 return ret;
00374 }
00375
00376 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/calculator/Calculator.cpp#2 $");
00377
00378