Skip to content

Commit

Permalink
Merge pull request #805 from hs-apotell/cmp
Browse files Browse the repository at this point in the history
Introducing uhdm-cmp tool to topographically compare two uhdm binaries
  • Loading branch information
alaindargelas authored Oct 17, 2022
2 parents 30936ad + 90357c8 commit 38fb743
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 16 deletions.
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,12 @@ if (UHDM_BUILD_TESTS)
endif()

# Useful utilities
add_executable(uhdm-cmp ${PROJECT_SOURCE_DIR}/util/uhdm-cmp.cpp)
target_link_libraries(uhdm-cmp PRIVATE uhdm)

add_executable(uhdm-dump ${PROJECT_SOURCE_DIR}/util/uhdm-dump.cpp)
target_link_libraries(uhdm-dump PRIVATE uhdm)

add_executable(uhdm-hier ${PROJECT_SOURCE_DIR}/util/uhdm-hier.cpp)
target_link_libraries(uhdm-hier PRIVATE uhdm)

Expand All @@ -270,7 +274,7 @@ target_link_libraries(test_inst PRIVATE

# Installation target
install(
TARGETS uhdm capnp kj uhdm-dump uhdm-hier
TARGETS uhdm capnp kj uhdm-cmp uhdm-dump uhdm-hier
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/uhdm
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/include/uhdm)
install(DIRECTORY ${GENDIR}/uhdm/
Expand Down
28 changes: 13 additions & 15 deletions scripts/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,16 +526,13 @@ def _get_GetVpiPropertyValue_implementation(model):
def _get_Compare_implementation(model):
vpi_blacklist = [
'uhdmId',
'uhdmParentType',
'uhdmType',
'vpiColumnNo',
'vpiEndColumnNo',
'vpiEndLineNo',
'vpiFile',
'vpiFullName',
'vpiInstance',
'vpiLineNo',
'vpiParent',
]

classname = model['name']
Expand All @@ -544,18 +541,21 @@ def _get_Compare_implementation(model):
includes = set()
content = [
f'int {classname}::Compare(const BaseClass *const other, AnySet& visited) const {{',
' int r = 0;',
' if (!visited.insert(this).second) return r;',
'',
' AnySet local;',
' if ((r = basetype_t::Compare(other, local)) != 0) return r;',
' visited.merge(local);',
''
' int r = 0;'
]

if not model['subclasses']:
# Mark self visited (and check) only for the most derived sub-class
content.append(' if (!visited.insert(this).second) return r;')

content.extend([
' if ((r = basetype_t::Compare(other, visited)) != 0) return r;',
''
])

var_declared = False
for key, value in model.allitems():
if key not in ['property', 'obj_ref', 'class_ref']:
if key not in ['property', 'obj_ref', 'class_ref', 'class']:
continue

vpi = value.get('vpi')
Expand Down Expand Up @@ -591,8 +591,7 @@ def _get_Compare_implementation(model):
f' auto lhs_{name} = lhs->{Name}();',
f' auto rhs_{name} = rhs->{Name}();',
f' if ((lhs_{name} != nullptr) && (rhs_{name} != nullptr)) {{',
f' if ((r = lhs_{name}->Compare(rhs_{name}, local)) != 0) return r;',
' visited.merge(local);',
f' if ((r = lhs_{name}->Compare(rhs_{name}, visited)) != 0) return r;',
f' }} else if ((lhs_{name} != nullptr) && (rhs_{name} == nullptr)) {{',
' return 1;',
f' }} else if ((lhs_{name} == nullptr) && (rhs_{name} != nullptr)) {{',
Expand All @@ -613,8 +612,7 @@ def _get_Compare_implementation(model):
f' if ((r = static_cast<int>(lhs_{name}->size() - rhs_{name}->size())) != 0) return r;',
'',
f' for (size_t i = 0, n = lhs_{name}->size(); i < n; ++i) {{',
f' if ((r = lhs_{name}->at(i)->Compare(rhs_{name}->at(i), local)) != 0) return r;',
' visited.merge(local);',
f' if ((r = lhs_{name}->at(i)->Compare(rhs_{name}->at(i), visited)) != 0) return r;',
' }',
f' }} else if ((lhs_{name} != nullptr) && (rhs_{name} == nullptr)) {{',
' return 1;',
Expand Down
105 changes: 105 additions & 0 deletions util/uhdm-cmp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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.
*/

#include <uhdm/uhdm.h>

#include <algorithm>
#include <filesystem>
#include <iostream>
#include <memory>
#include <string>

namespace fs = std::filesystem;

static int32_t usage(const char *progName) {
std::cerr << "Usage:" << std::endl
<< " " << progName << " <uhdm-file> <uhdm-file>" << std::endl
<< std::endl
<< "Reads input uhdm binary representations of two files and "
"compares them topographically."
<< std::endl
<< std::endl
<< "Exits with code" << std::endl
<< " = 0, if input files are equal" << std::endl
<< " < 0, if input files are not equal" << std::endl
<< " > 0, for any failures" << std::endl;
return 1;
}

int32_t main(int32_t argc, char **argv) {
if (argc != 3) {
return usage(argv[0]);
}

fs::path fileA = argv[1];
fs::path fileB = argv[2];

std::error_code ec;
if (!fs::is_regular_file(fileA, ec) || ec) {
std::cerr << fileA << ": File does not exist!" << std::endl;
return usage(argv[0]);
}

if (!fs::is_regular_file(fileB, ec) || ec) {
std::cerr << fileB << ": File does not exist!" << std::endl;
return usage(argv[0]);
}

std::unique_ptr<UHDM::Serializer> serializerA(new UHDM::Serializer);
std::vector<vpiHandle> handlesA = serializerA->Restore(fileA);

std::unique_ptr<UHDM::Serializer> serializerB(new UHDM::Serializer);
std::vector<vpiHandle> handlesB = serializerB->Restore(fileB);

if (handlesA.empty()) {
std::cerr << fileA << ": Failed to load." << std::endl;
return 1;
}

if (handlesB.empty()) {
std::cerr << fileB << ": Failed to load." << std::endl;
return 1;
}

if (handlesA.size() != handlesB.size()) {
std::cerr << "Number of designs mismatch." << std::endl;
return -1;
}

std::function<const UHDM::design *(vpiHandle handle)> to_design =
[](vpiHandle handle) {
return (const UHDM::design *)((const uhdm_handle *)handle)->object;
};

std::vector<const UHDM::design *> designsA;
designsA.reserve(handlesA.size());
std::transform(handlesA.begin(), handlesA.end(), std::back_inserter(designsA),
to_design);

std::vector<const UHDM::design *> designsB;
designsB.reserve(handlesB.size());
std::transform(handlesB.begin(), handlesB.end(), std::back_inserter(designsB),
to_design);

for (size_t i = 0, n = designsA.size(); i < n; ++i) {
UHDM::AnySet visited;
if (designsA[i]->Compare(designsB[i], visited) != 0) {
return -1;
}
}

return 0;
}

0 comments on commit 38fb743

Please sign in to comment.