| /* | |
| Copyright 2019 Alain Dargelas | |
| Licensed under the Apache License, Version 2.0 (the "License"); | |
| you may not use this file except in compliance with the License. | |
| You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| */ | |
| /* | |
| * File: CheckCompile.cpp | |
| * Author: alain | |
| * | |
| * Created on June 10, 2017, 10:15 PM | |
| */ | |
| #include <iostream> | |
| #include <set> | |
| #include "SourceCompile/SymbolTable.h" | |
| #include "Design/TimeInfo.h" | |
| #include "Design/DesignElement.h" | |
| #include "Design/FileContent.h" | |
| #include "ErrorReporting/Location.h" | |
| #include "ErrorReporting/Error.h" | |
| #include "ErrorReporting/ErrorDefinition.h" | |
| #include "ErrorReporting/ErrorContainer.h" | |
| #include "SourceCompile/CompilationUnit.h" | |
| #include "SourceCompile/PreprocessFile.h" | |
| #include "SourceCompile/CompileSourceFile.h" | |
| #include "SourceCompile/Compiler.h" | |
| #include "SourceCompile/ParseFile.h" | |
| #include "CommandLine/CommandLineParser.h" | |
| #include "SourceCompile/CheckCompile.h" | |
| using namespace SURELOG; | |
| CheckCompile::~CheckCompile() {} | |
| bool CheckCompile::check() { | |
| if (!mergeSymbolTables_()) return false; | |
| if (!checkTimescale_()) return false; | |
| return true; | |
| } | |
| bool CheckCompile::mergeSymbolTables_() { | |
| Design::FileIdDesignContentMap& all_files = | |
| m_compiler->getDesign()->getAllFileContents(); | |
| for (auto fitr = all_files.begin(); fitr != all_files.end(); fitr++) { | |
| auto fileContent = (*fitr).second; | |
| m_compiler->getSymbolTable()->registerSymbol(fileContent->getFileName()); | |
| for (NodeId id : fileContent->getNodeIds()) { | |
| fileContent->getFileId(id) = m_compiler->getSymbolTable()->registerSymbol( | |
| fileContent->getSymbolTable()->getSymbol(fileContent->getFileId(id))); | |
| } | |
| for (DesignElement& elem : fileContent->getDesignElements()) { | |
| elem.m_name = m_compiler->getSymbolTable()->registerSymbol( | |
| fileContent->getSymbolTable()->getSymbol(elem.m_name)); | |
| elem.m_fileId = m_compiler->getSymbolTable()->registerSymbol( | |
| fileContent->getSymbolTable()->getSymbol( | |
| fileContent->getFileId(elem.m_node))); | |
| } | |
| } | |
| return true; | |
| } | |
| bool CheckCompile::checkTimescale_() { | |
| std::string globaltimescale = | |
| m_compiler->getCommandLineParser()->getTimeScale(); | |
| if (globaltimescale != "") { | |
| Location loc(0, 0, 0, | |
| m_compiler->getSymbolTable()->registerSymbol(globaltimescale)); | |
| Error err(ErrorDefinition::CMD_USING_GLOBAL_TIMESCALE, loc); | |
| m_compiler->getErrorContainer()->addError(err); | |
| return true; | |
| } | |
| bool timeUnitUsed = false; | |
| bool timeScaleUsed = false; | |
| std::vector<Location> noTimeUnitLocs; | |
| Design::FileIdDesignContentMap& all_files = | |
| m_compiler->getDesign()->getAllFileContents(); | |
| std::unordered_set<SymbolId> reportedMissingTimescale; | |
| std::unordered_set<SymbolId> reportedMissingTimeunit; | |
| for (auto fitr = all_files.begin(); fitr != all_files.end(); fitr++) { | |
| auto fileContent = (*fitr).second; | |
| for (auto elem : fileContent->getDesignElements()) { | |
| if (elem.m_type == DesignElement::Module || | |
| elem.m_type == DesignElement::Interface || | |
| elem.m_type == DesignElement::Package || | |
| elem.m_type == DesignElement::Primitive || | |
| elem.m_type == DesignElement::Program) { | |
| if (elem.m_timeInfo.m_type == TimeInfo::TimeUnitTimePrecision) { | |
| timeUnitUsed = true; | |
| } else if (elem.m_timeInfo.m_type == TimeInfo::Timescale) { | |
| timeScaleUsed = true; | |
| Location loc(m_compiler->getSymbolTable()->registerSymbol( | |
| fileContent->getSymbolTable()->getSymbol( | |
| fileContent->getFileId(elem.m_node))), | |
| elem.m_line, 0, elem.m_name); | |
| noTimeUnitLocs.push_back(loc); | |
| } else { | |
| Location loc(m_compiler->getSymbolTable()->registerSymbol( | |
| fileContent->getSymbolTable()->getSymbol( | |
| fileContent->getFileId(elem.m_node))), | |
| elem.m_line, 0, elem.m_name); | |
| noTimeUnitLocs.push_back(loc); | |
| if (reportedMissingTimescale.find(elem.m_name) == | |
| reportedMissingTimescale.end()) { | |
| reportedMissingTimescale.insert(elem.m_name); | |
| Error err(ErrorDefinition::PA_NOTIMESCALE_INFO, loc); | |
| m_compiler->getErrorContainer()->addError(err); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if (timeUnitUsed && timeScaleUsed) { | |
| for (auto loc : noTimeUnitLocs) { | |
| if (reportedMissingTimeunit.find(loc.m_object) == | |
| reportedMissingTimeunit.end()) { | |
| reportedMissingTimeunit.insert(loc.m_object); | |
| Error err(ErrorDefinition::PA_MISSING_TIMEUNIT, loc); | |
| m_compiler->getErrorContainer()->addError(err); | |
| } | |
| } | |
| } | |
| return true; | |
| } |