/* `Deep Thought', a softcore CPU implemented on a FPGA Copyright (C) 2010 Markus Hofstaetter Copyright (C) 2010 Martin Perner Copyright (C) 2010 Stefan Rebernig Copyright (C) 2010 Manfred Schwarz Copyright (C) 2010 Bernhard Urban This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "CInstrFactory.hpp" using namespace std; /** * Name: loadFromLib * Purpose: loads a command from the given library file * Parameter: std::string lib location of the library file * Preconditions: lib references to a valid library */ Iinstr* CInstrFactory::loadFromLib(string lib) { Iinstr* (*create_instruction)(); // load a Instruction from library void* instruction = dlopen(lib.c_str(), RTLD_LAZY); if (!instruction) { cerr << "Cannot load library: " << dlerror() << endl; exit(EXIT_FAILURE); } // load the symbols void* create = dlsym(instruction, "create_instruction"); void* destroy = dlsym(instruction, "destroy_instruction"); if (!create || !destroy) { cerr << "Cannot load symbols: " << dlerror() << endl; dlclose(instruction); exit(EXIT_FAILURE); } memcpy(&create_instruction, &create, sizeof(create)); Iinstr* instructionPointer = create_instruction(); m_libStore.insert(make_pair(instruction, instructionPointer)); return instructionPointer; } /** * Name: getNextInstruction * Purpose: returns a pointer to a command * Returns: Pointer to the loaded command * Throw: string * Preconditions: a command is left to load */ Iinstr* CInstrFactory::getNextInstr() { if(m_files.size() >= 1) { Iinstr* instruction; instruction = loadFromLib(m_files[0]); m_files.erase(m_files.begin()); return instruction; } else { throw string("No more instruction left!"); } } /** * Name: searchLibsInDir * Purpose: finds librarys in the given directory * Returns: number of found librarays * Parameters: std::string dir Directory where the libraries are located * Throw: string * Postconditions: all files with a trailing '.so' are ready to be used */ size_t CInstrFactory::searchLibsInDir(string dir) { DIR *dp; if((dp = opendir(dir.c_str())) == NULL) { stringstream errmsg; errmsg << "Error(" << errno << ") opening " << dir << endl; throw errmsg.str(); } struct dirent *dirp; while ((dirp = readdir(dp)) != NULL) { string file = dirp->d_name; if(file.size() >= 3) { file = file.substr(file.size()-3); std::transform(file.begin(), file.end(), file.begin(), ::tolower); if(file == ".so") { m_files.push_back(dir+"/"+string(dirp->d_name)); } } } closedir(dp); return m_files.size(); } /** * Name: getNumFiles * Purpose: returns the number of librarys left * Returns: size_t number of files left */ size_t CInstrFactory::getNumFiles() { return m_files.size(); } void CInstrFactory::loadLibsIntoMap(map& instr, string dir) { #ifdef DEBUG cout << "Loaded " << this->searchLibsInDir(dir) << " Libraryfiles" << endl; #else this->searchLibsInDir(dir); #endif while(this->getNumFiles() >= 1) { Iinstr* pinstr = this->getNextInstr(); instr.insert(make_pair(pinstr->getOpcode(),pinstr)); #ifdef DEBUG cout << "found: " << pinstr->getName() << " its opcode is : " << pinstr->getOpcode() << endl; #endif } } /** * Name: ~CInstrFactory * Purpose: Destructor of the Object */ CInstrFactory::~CInstrFactory() { void (*destroy_instruction)(Iinstr*); while(!m_libStore.empty()) { void* destroy = dlsym(m_libStore.begin()->first, "destroy_instruction"); memcpy(&destroy_instruction, &destroy, sizeof(destroy)); destroy_instruction(m_libStore.begin()->second); dlclose(m_libStore.begin()->first); m_libStore.erase(m_libStore.begin()); } }