diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c64baf..fa1947a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) find_package(SDL2 CONFIG REQUIRED) find_package(SDL2_ttf CONFIG REQUIRED) +add_definitions(-DROOT_DIR="${CMAKE_SOURCE_DIR}") + add_subdirectory(extern/pugixml-1.13) add_subdirectory(extern/lorina/lib) diff --git a/assets/img/gates.bmp b/assets/img/gates.bmp new file mode 100644 index 0000000..e0d0169 Binary files /dev/null and b/assets/img/gates.bmp differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd9317d..6a8b9cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,4 +4,5 @@ target_link_libraries(main SDL2::SDL2 SDL2_ttf::SDL2_ttf pugixml::pugixml - Lorina) \ No newline at end of file + Lorina + cli11) \ No newline at end of file diff --git a/src/layout.cpp b/src/layout.cpp old mode 100644 new mode 100755 index d217b49..468fa7e --- a/src/layout.cpp +++ b/src/layout.cpp @@ -294,10 +294,11 @@ void addAllDummyNodes( } } -TreeNode::Id Net::addNode() { +TreeNode::Id Net::addNode(Type type) { Id id = static_cast(nodes.size()); nodes.emplace_back(); nodes.back().id = id; + nodes.back().type = type; return id; } @@ -363,13 +364,19 @@ enum { void initPositionAndSize( std::vector &nodes, - std::vector &normalizedElements, - float nCellSize) { + std::vector &normalizedElements, + float nCellSize, + bool initDummy) { for (TreeNode &node : nodes) { - NormalizedElement nElement = {}; + Element nElement = {}; nElement.id = node.id; + nElement.scrType.setType(node.type); if (node.isDummy) { + if (!initDummy) { + continue; + } + NormalizedPoint nPoint = {}; nPoint.nX = nCellSize * node.number + (nCellSize / ReductionWidth) / ReductionRelationToGap; @@ -393,13 +400,26 @@ void initPositionAndSize( } } +static TreeNode::Id +traceVirtualNode(TreeNode::Id originId, const std::vector &nodes) { + const TreeNode *node = nodes.data() + originId; + while (node->isDummy) { + node = nodes.data() + node->succ[0]; + } + return node->id; +} + void initConnections( - std::vector &nodes, - std::vector &normalizedElements) { + const std::vector &nodes, + std::vector &normalizedElements, + bool initDummy) { int countConnections = 0; for (size_t i = 0; i < nodes.size(); i++) { - for (size_t &succId : nodes[i].succ) { - NormalizedConnection connection = {}; + if (nodes[i].isDummy && !initDummy) { + continue; + } + for (size_t succId : nodes[i].succ) { + Connection connection = {}; connection.id = countConnections; connection.startElementId = nodes[i].id; @@ -411,6 +431,9 @@ void initConnections( nPointStart.nY = normalizedElements[i].nPoint.nY + normalizedElements[i].nH; + if (!initDummy) { + succId = traceVirtualNode(succId, nodes); + } NormalizedPoint nPointEnd = {}; nPointEnd.nX = normalizedElements[succId].nPoint.nX + normalizedElements[succId].nW / GetMiddle; @@ -427,7 +450,8 @@ void initConnections( } void Net::netTreeNodesToNormalizedElements( - std::vector &normalizedElements) { + std::vector &normalizedElements, + bool showDummy) { float maxNumber = -1, maxLayer = -1; for (TreeNode &node : nodes) { if (node.layer > maxLayer) { @@ -445,7 +469,7 @@ void Net::netTreeNodesToNormalizedElements( nCellSize = 1 / (maxNumber + 1); } - initPositionAndSize(nodes, normalizedElements, nCellSize); + initPositionAndSize(nodes, normalizedElements, nCellSize, showDummy); - initConnections(nodes, normalizedElements); + initConnections(nodes, normalizedElements, showDummy); } diff --git a/src/layout.h b/src/layout.h index 0bb0e6b..fc65406 100644 --- a/src/layout.h +++ b/src/layout.h @@ -19,6 +19,7 @@ struct TreeNode { std::vector succ = {}; std::vector pred = {}; Id id = 0; + Type type = NONE; int layer = 0; int number = 0; bool isDummy = false; @@ -42,7 +43,7 @@ struct Net { const std::vector &getSuccessors(Id id) const; const std::vector &getPredecessors(Id id) const; - Id addNode(); + Id addNode(Type type); TreeNode *getNode(Id id) { const Net &net = *this; @@ -53,7 +54,8 @@ struct Net { void assignLayers(); void netTreeNodesToNormalizedElements( - std::vector &normalizedElements); + std::vector &normalizedElements, + bool showDummy); std::vector> getNodesByLayer(); }; diff --git a/src/main.cpp b/src/main.cpp index 7c79ccb..83b1ee1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,12 +8,15 @@ #define SDL_MAIN_HANDLED #include "pugixml.hpp" +#include #include #include #include - #include +#include +#include + #include "layout.h" #include "netfmt_bench.h" #include "main.h" @@ -22,7 +25,7 @@ enum StatusCode { SUCCESS = 0, FILENAME_NOT_PROVIDED, - PARSER_FAILURE, + RAW_PARSER_FAILURE, SDL_INIT_FAILURE, BENCH_READER_ERROR }; @@ -30,24 +33,50 @@ enum StatusCode { const char *statusMessages[] = { "Success\n", "Filename was not provided\n", - "Parser failure\n", - "SDL could not be initialized\n" + "Raw parser failure\n", + "SDL could not be initialized\n", + "Bench reader error\n" }; const char *const parserElementId = "e_id"; -const char *const parserConnetionId = "c_id"; +const char *const parserConnectionId = "c_id"; const char *const parserX = "x"; const char *const parserY = "y"; const char *const parserHeight = "height"; const char *const parserWidth = "width"; const char *const parserEndElement = "end_element"; +const char *const parserLogicScheme = "logic_scheme"; +const char *const parserElements = "elements"; +const char *const parserConnections = "connections"; +const char *const parserOutlineColor = "outline_color"; +const char *const parserFillColor = "fill_color"; +const char *const parserColor = "color"; +const char *const parserBackColor = "background_color"; +const char *const parserR = "r"; +const char *const parserG = "g"; +const char *const parserB = "b"; const float zoomInScalingFactor = 1.1f; const float zoomOutScalingFactor = 0.9f; const float mouseWheelScalingFactor = 0.1f; -const std::string printCompactMode = "--compact"; -const std::string printDefaultMode = "--default"; +const float inf = std::numeric_limits::infinity(); + +const unsigned int framesNum = 100; + +const std::string optionFile = "file"; +const std::string flagFPS = "--fps"; +const std::string flagRaw = "--raw"; +const std::string flagCompact = "--compact"; +const std::string flagMinimize = "--minimize"; +const std::string flagColors = "--colors"; +const std::string flagDummy = "--dummy"; +const std::string flagTexture = "--texturize"; + +const std::string texturePath = + std::string(ROOT_DIR) + + std::string("/assets/img/gates.bmp"); +SDL_Texture *gatesTexture = NULL; float normalizedToScreenX(const float nX, const int screenW) { return nX * screenW; @@ -57,23 +86,58 @@ float normalizedToScreenY(const float nY, const int screenH) { return nY * screenH; } -void NormalizedElement::move(const int dx, const int dy) { +void ScreenType::setType(Type type) { + switch (type) { + case INPUT: + textureRect = {0, 1838, 604, 186}; + break; + case OUTPUT: + textureRect = {988, 1838, 604, 186}; + break; + case AND: + textureRect = {0, 0, 607, 321}; + break; + case NAND: + textureRect = {832, 0, 653, 321}; + break; + case OR: + textureRect = {30, 701, 623, 321}; + break; + case NOR: + textureRect = {861, 701, 672, 321}; + break; + case NOT: + textureRect = {0, 2122, 505, 278}; + break; + case DFF: + textureRect = {0, 1176, 512, 506}; + break; + default: + break; + } +} + +Type ScreenType::getType() const { + return type; +} + +void Element::move(const int dx, const int dy) { scrRect.x += dx; scrRect.y += dy; - for (NormalizedConnection &connectionToMove : connections) { + for (Connection &connectionToMove : connections) { connectionToMove.move(dx, dy); } } -void NormalizedConnection::move(const int dx, const int dy) { +void Connection::move(const int dx, const int dy) { for (SDL_FPoint &vertexToMove : scrVertices) { vertexToMove.x += dx; vertexToMove.y += dy; } } -void NormalizedElement::scale( +void Element::scale( const float scalingFactor, const int mouseX, const int mouseY) { @@ -82,12 +146,12 @@ void NormalizedElement::scale( scrRect.w *= scalingFactor; scrRect.h *= scalingFactor; - for (NormalizedConnection &connectionToScale : connections) { + for (Connection &connectionToScale : connections) { connectionToScale.scale(scalingFactor, mouseX, mouseY); } } -void NormalizedConnection::scale( +void Connection::scale( const float scalingFactor, const int mouseX, const int mouseY) { @@ -97,7 +161,7 @@ void NormalizedConnection::scale( } } -void NormalizedConnection::normalizedToScreen( +void Connection::normalizedToScreen( const int screenW, const int screenH) { for (const NormalizedPoint &nVertex : nVertices) { @@ -108,7 +172,7 @@ void NormalizedConnection::normalizedToScreen( } } -void NormalizedElement::normalizedToScreen( +void Element::normalizedToScreen( const int screenW, const int screenH) { scrRect.x = normalizedToScreenX(nPoint.nX, screenW); @@ -117,48 +181,103 @@ void NormalizedElement::normalizedToScreen( scrRect.h = normalizedToScreenY(nH, screenH); } -void drawBackground(SDL_Renderer *renderer) { - SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); +void drawBackground(SDL_Renderer *renderer, + const SDL_Color &backgroundColor, + const bool drawColor) { + if (drawColor) { + SDL_SetRenderDrawColor(renderer, + backgroundColor.r, + backgroundColor.g, + backgroundColor.b, + SDL_ALPHA_OPAQUE); + } else { + SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); + } SDL_RenderClear(renderer); } int parseInput( - const char *filename, - std::vector &elementsToParse) { + std::istream &stream, + std::vector &elementsToParse, + SDL_Color &backgroundColor) { pugi::xml_document file; - if (!file.load_file(filename)) { - return PARSER_FAILURE; + if (!file.load(stream)) { + return RAW_PARSER_FAILURE; } - pugi::xml_node elements = file.child("logic_scheme").child("elements"); + pugi::xml_node parsedBackColor = file.child(parserLogicScheme).child(parserBackColor); + backgroundColor.r = parsedBackColor.attribute(parserR).as_int(255); + backgroundColor.g = parsedBackColor.attribute(parserG).as_int(255); + backgroundColor.b = parsedBackColor.attribute(parserB).as_int(255); + + pugi::xml_node elements = file.child(parserLogicScheme).child(parserElements); // Parsing elements from given file for (pugi::xml_node element = elements.first_child(); element; element = element.next_sibling()) { - NormalizedElement parsedElement; - parsedElement.id = atoi(element.attribute(parserElementId).value()); - parsedElement.nPoint.nX = std::stof(element.attribute(parserX).value()); - parsedElement.nPoint.nY = std::stof(element.attribute(parserY).value()); - parsedElement.nH = std::stof(element.attribute(parserHeight).value()); - parsedElement.nW = std::stof(element.attribute(parserWidth).value()); - + Element parsedElement; + parsedElement.id = element.attribute(parserElementId).as_int(-1); + parsedElement.nPoint.nX = element.attribute(parserX).as_float(); + parsedElement.nPoint.nY = element.attribute(parserY).as_float(); + parsedElement.nH = element.attribute(parserHeight).as_float(); + parsedElement.nW = element.attribute(parserWidth).as_float(); + + // Reading outline color from the document and if there is not one detected + // Defaults to cyan RGB(3, 161, 252) + pugi::xml_node outlineColor = element.child(parserOutlineColor); + if (outlineColor) { + parsedElement.outlineColor.r = outlineColor.attribute(parserR).as_int(); + parsedElement.outlineColor.g = outlineColor.attribute(parserG).as_int(); + parsedElement.outlineColor.b = outlineColor.attribute(parserB).as_int(); + } + else { + parsedElement.outlineColor.r = 3; + parsedElement.outlineColor.g = 161; + parsedElement.outlineColor.b = 252; + } + // Reading fill color from the document and if there is not one detected + // Defaults to cyan RGB(3, 161, 252) + pugi::xml_node fillColor = element.child(parserFillColor); + if (fillColor) { + parsedElement.fillColor.r = fillColor.attribute(parserR).as_int(); + parsedElement.fillColor.g = fillColor.attribute(parserG).as_int(); + parsedElement.fillColor.b = fillColor.attribute(parserB).as_int(); + } else { + parsedElement.fillColor.r = 3; + parsedElement.fillColor.g = 161; + parsedElement.fillColor.b = 252; + } // Parsing connections for given element - for (pugi::xml_node connection = element.first_child(); + pugi::xml_node connections = element.child(parserConnections); + for (pugi::xml_node connection = connections.first_child(); connection; connection = connection.next_sibling()) { - NormalizedConnection parsedConnection; - parsedConnection.id = atoi(connection.attribute(parserConnetionId).value()); + Connection parsedConnection; + parsedConnection.id = atoi(connection.attribute(parserConnectionId).value()); parsedConnection.startElementId = parsedElement.id; parsedConnection.endElementId = atoi(connection.attribute(parserEndElement).value()); + // Reading color from the document and if there is not one detected + // Defaults to black RGB(0, 0, 0) + pugi::xml_node color = connection.child(parserColor); + if (color) { + parsedConnection.color.r = color.attribute(parserR).as_int(); + parsedConnection.color.g = color.attribute(parserG).as_int(); + parsedConnection.color.b = color.attribute(parserB).as_int(); + } else { + parsedConnection.color.r = 0; + parsedConnection.color.g = 0; + parsedConnection.color.b = 0; + } // Parsing nVertices for given connection - for (pugi::xml_node vertex = connection.first_child(); + pugi::xml_node vertices = connection.child("vertices"); + for (pugi::xml_node vertex = vertices.first_child(); vertex; vertex = vertex.next_sibling()) { NormalizedPoint parsedVertex; - parsedVertex.nX = std::stof(vertex.attribute(parserX).value()); - parsedVertex.nY = std::stof(vertex.attribute(parserY).value()); + parsedVertex.nX = vertex.attribute(parserX).as_float(); + parsedVertex.nY = vertex.attribute(parserY).as_float(); parsedConnection.nVertices.push_back(parsedVertex); } parsedElement.connections.push_back(parsedConnection); @@ -170,12 +289,12 @@ int parseInput( std::ostream &operator<<( std::ostream &out, - const NormalizedElement &elementToPrint) { + const Element &elementToPrint) { out << "Element id: " << elementToPrint.id << " x: " << elementToPrint.nPoint.nX << " y: " << elementToPrint.nPoint.nY << std::endl; - for (const NormalizedConnection &connection : elementToPrint.connections) { + for (const Connection &connection : elementToPrint.connections) { out << " Connection id: " << connection.id; for (size_t i = 0; i < connection.nVertices.size(); i++) { out << " x" << i << ": " << connection.nVertices[i].nX @@ -187,11 +306,11 @@ std::ostream &operator<<( } void print( - const std::string &printMode, - const std::vector &elementsToPrint) { - if (printMode == printCompactMode) { + const std::vector &elementsToPrint, + bool printCompact) { + if (printCompact) { size_t connectionsCount = 0; - for (const NormalizedElement &element : elementsToPrint) { + for (const Element &element : elementsToPrint) { connectionsCount += element.connections.size(); } std::cout << "Number of elements: " @@ -199,43 +318,168 @@ void print( << "\nNumber of connections: " << connectionsCount << std::endl; - } else if (printMode == printDefaultMode) { - for (const NormalizedElement &element : elementsToPrint) { + } else { + for (const Element &element : elementsToPrint) { std::cout << element; } } } void convertNormToScreen( - std::vector &elementsToConvert, + std::vector &elementsToConvert, const int screenW, const int screenH) { // Converting normalized coordinates to screen - for (NormalizedElement &nElem : elementsToConvert) { + for (Element &nElem : elementsToConvert) { nElem.normalizedToScreen(screenW, screenH); - for (NormalizedConnection &nConnection : nElem.connections) { + for (Connection &nConnection : nElem.connections) { nConnection.normalizedToScreen(screenW, screenH); } } } +float maxi(const float arr[], int n) { + float m = 0; + for (int i = 0; i < n; ++i) + if (m < arr[i]) + m = arr[i]; + return m; +} + +float mini(const float arr[], int n) { + float m = 1; + for (int i = 0; i < n; ++i) + if (m > arr[i]) + m = arr[i]; + return m; +} + +bool checkSegmentRectCollision( + SDL_FPoint &point1, + SDL_FPoint &point2, + const int screenW, + const int screenH) { + float x1 = point1.x; + float y1 = point1.y; + float x2 = point2.x; + float y2 = point2.y; + + float p1 = -(x2 - x1); + float p2 = -p1; + float p3 = -(y2 - y1); + float p4 = -p3; + + float q1 = x1; + float q2 = screenW - x1; + float q3 = y1; + float q4 = screenH - y1; + + float posarr[5], negarr[5]; + int posind = 1, negind = 1; + posarr[0] = 1; + negarr[0] = 0; + + if ((p1 == 0 && q1 < 0) || (p3 == 0 && q3 < 0)) { + return false; + } + if (p1 != 0) { + float r1 = q1 / p1; + float r2 = q2 / p2; + if (p1 < 0) { + negarr[negind++] = r1; + posarr[posind++] = r2; + } else { + negarr[negind++] = r2; + posarr[posind++] = r1; + } + } + if (p3 != 0) { + float r3 = q3 / p3; + float r4 = q4 / p4; + if (p3 < 0) { + negarr[negind++] = r3; + posarr[posind++] = r4; + } else { + negarr[negind++] = r4; + posarr[posind++] = r3; + } + } + float rn1, rn2; + + rn1 = maxi(negarr, negind); + rn2 = mini(posarr, posind); + + if (rn1 > rn2) { + return false; + } + point1.x = x1 + p2 * rn1; + point1.y = y1 + p4 * rn1; + + point2.x = x1 + p2 * rn2; + point2.y = y1 + p4 * rn2; + + return true; +} + void drawFrame( SDL_Renderer *renderer, - const std::vector &elementsToDraw) { - drawBackground(renderer); + const std::vector &elementsToDraw, + const SDL_Color &backgroundColor, + const int screenW, + const int screenH, + const bool drawColor, + const bool texturize) { + drawBackground(renderer, backgroundColor, drawColor); SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); - for (const NormalizedElement &elementToDraw : elementsToDraw) { - SDL_RenderDrawRectF(renderer, &elementToDraw.scrRect); - for (const NormalizedConnection &connectionToDraw : elementToDraw.connections) { + for (const Element &elementToDraw : elementsToDraw) { + if (drawColor && !texturize) { + SDL_SetRenderDrawColor(renderer, + elementToDraw.fillColor.r, + elementToDraw.fillColor.g, + elementToDraw.fillColor.b, + SDL_ALPHA_OPAQUE); + SDL_RenderFillRectF(renderer, &elementToDraw.scrRect); + + SDL_SetRenderDrawColor(renderer, + elementToDraw.outlineColor.r, + elementToDraw.outlineColor.g, + elementToDraw.outlineColor.b, + SDL_ALPHA_OPAQUE); + } + if (texturize) { + SDL_RenderCopyF(renderer, + gatesTexture, + &elementToDraw.scrType.textureRect, + &elementToDraw.scrRect); + } else { + SDL_RenderDrawRectF(renderer, &elementToDraw.scrRect); + } + for (const Connection &connectionToDraw : elementToDraw.connections) { + if (drawColor) { + SDL_SetRenderDrawColor(renderer, + connectionToDraw.color.r, + connectionToDraw.color.g, + connectionToDraw.color.b, + SDL_ALPHA_OPAQUE); + } for (size_t i = 1; i < connectionToDraw.scrVertices.size(); i++) { - SDL_RenderDrawLineF(renderer, - connectionToDraw.scrVertices[i - 1].x, - connectionToDraw.scrVertices[i - 1].y, - connectionToDraw.scrVertices[i].x, - connectionToDraw.scrVertices[i].y); + SDL_FPoint point1 = connectionToDraw.scrVertices[i - 1]; + SDL_FPoint point2 = connectionToDraw.scrVertices[i]; + + bool collision = checkSegmentRectCollision(point1, + point2, + screenW, + screenH); + if (collision) { + SDL_RenderDrawLineF(renderer, + point1.x, + point1.y, + point2.x, + point2.y); + } } } } @@ -244,11 +488,11 @@ void drawFrame( void scaleViewport( const float scalingFactor, - std::vector &elementsToScale) { + std::vector &elementsToScale) { int mouseX, mouseY; SDL_GetMouseState(&mouseX, &mouseY); - for (NormalizedElement &elementToScale : elementsToScale) { + for (Element &elementToScale : elementsToScale) { elementToScale.scale(scalingFactor, mouseX, mouseY); } } @@ -256,8 +500,8 @@ void scaleViewport( void moveViewport( const int dx, const int dy, - std::vector &elementsToScale) { - for (NormalizedElement &elementToScale : elementsToScale) { + std::vector &elementsToScale) { + for (Element &elementToScale : elementsToScale) { elementToScale.move(dx, dy); } } @@ -266,35 +510,101 @@ float scaleMouseWheel(const Sint32 mouseWheelY) { return 1 + mouseWheelY * mouseWheelScalingFactor; } -int main(int argc, char *argv[]) { - // Parse text file - if (argc < 2) { - std::cerr << statusMessages[FILENAME_NOT_PROVIDED]; - return FILENAME_NOT_PROVIDED; - } - - std::string printMode = printDefaultMode; - if (argc >= 3) { - printMode = argv[2]; - } - - Net net = {}; - std::ifstream ifs(argv[1]); - if (!readNetFromBench(ifs, net)) { - return BENCH_READER_ERROR; +void defaultColor(std::vector &elementsToColor, SDL_Color &backgroundColor) { + for (Element &elementToColor : elementsToColor) { + elementToColor.fillColor = {3, 161, 252, 255}; + elementToColor.outlineColor = {3, 161, 252, 255}; + for (Connection &connectionToColor : elementToColor.connections) { + connectionToColor.color = {0, 0, 0, 255}; + } } + backgroundColor = {255, 255, 255, 255}; +} - net.assignLayers(); - minimizeIntersections(net); - std::vector normalizedElements = {}; - net.netTreeNodesToNormalizedElements(normalizedElements); - +int main(int argc, char *argv[]) { + std::cout << ROOT_DIR; + CLI::App cliApp; + + std::string filename; + cliApp.add_option(optionFile, + filename, + "File to parse")->required(); + + bool parseRaw = false; + auto cliRaw = cliApp.add_flag(flagRaw, + parseRaw, + "Parse graph represented as FLG file"); + + bool printCompact = false; + cliApp.add_flag(flagCompact, + printCompact, + "Print quantity of elements and connections"); + + bool drawColor = false; + cliApp.add_flag(flagColors, + drawColor, + "Draw color"); + + bool showFPS = false; + cliApp.add_flag(flagFPS, + showFPS, + "Show average frame time, FPS and BENCH file processing time"); + + bool processMinimize = false; + cliApp.add_flag(flagMinimize, + processMinimize, + "Minimize intersections")->excludes(cliRaw); + + bool showDummy = false; + cliApp.add_flag(flagDummy, + showDummy, + "Show dummy nodes")->excludes(cliRaw); + + bool texturize = false; + cliApp.add_flag(flagTexture, + texturize, + "Texturize nodes"); + + CLI11_PARSE(cliApp, argc, argv); + + std::ifstream ifs(filename); + std::vector normalizedElements = {}; + SDL_Color backgroundColor; + if (parseRaw) { + if (parseInput(ifs, normalizedElements, backgroundColor)) { + std::cerr << statusMessages[RAW_PARSER_FAILURE]; + return RAW_PARSER_FAILURE; + } + } else { + Net net = {}; + if (!readNetFromBench(ifs, net)) { + std::cerr << statusMessages[BENCH_READER_ERROR]; + return BENCH_READER_ERROR; + } + auto start = std::chrono::high_resolution_clock::now(); + net.assignLayers(); + if (processMinimize) { + minimizeIntersections(net); + } + net.netTreeNodesToNormalizedElements(normalizedElements, showDummy); + auto stop = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(stop - start).count(); + if (showFPS) { + std::cout << "BENCH processing time: " + << duration + << " ms." + << std::endl; + } + defaultColor(normalizedElements, backgroundColor); + } // Prepare draw data and draw if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cerr << statusMessages[SDL_INIT_FAILURE]; return SDL_INIT_FAILURE; } + print(normalizedElements, printCompact); + std::cout << statusMessages[SUCCESS]; // Get screen dimensions @@ -307,9 +617,12 @@ int main(int argc, char *argv[]) { SDL_CreateWindow("test-viz", 0, 0, screenW, screenH, SDL_WINDOW_SHOWN); SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + SDL_Surface *gatesSurface = SDL_LoadBMP(texturePath.c_str()); + gatesTexture = SDL_CreateTextureFromSurface(renderer, gatesSurface); + SDL_FreeSurface(gatesSurface); convertNormToScreen(normalizedElements, screenW, screenH); - drawFrame(renderer, normalizedElements); + drawFrame(renderer, normalizedElements, backgroundColor, screenW, screenH, drawColor, texturize); // Event loop bool isRunning = true; @@ -318,7 +631,26 @@ int main(int argc, char *argv[]) { int mouseY1 = 0; int mouseX2 = 0; int mouseY2 = 0; + + auto start = std::chrono::high_resolution_clock::now(); + unsigned int count = 0; while (isRunning) { + if (count == framesNum) { + auto stop = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(stop - start).count(); + auto avgFrameTime = duration / count; + auto avgFPS = 1000/avgFrameTime; + start = std::chrono::high_resolution_clock::now(); + count = 0; + if (showFPS) { + std::cout << "Avg frame time: " + << avgFrameTime + << " ms. FPS:" + << avgFPS + << std::endl; + } + } + count++; SDL_Event event; // User input handler while (SDL_PollEvent(&event)) { @@ -335,7 +667,6 @@ int main(int argc, char *argv[]) { mouseY2 = 0; } else if (isDragging && SDL_GetMouseState(&mouseX2, &mouseY2)) { moveViewport(mouseX2 - mouseX1, mouseY2 - mouseY1, normalizedElements); - drawFrame(renderer, normalizedElements); SDL_GetMouseState(&mouseX1, &mouseY1); } else if (event.type == SDL_KEYDOWN) { // Keyboard input handler @@ -350,15 +681,16 @@ int main(int argc, char *argv[]) { isRunning = false; break; } - drawFrame(renderer, normalizedElements); } else if (event.type == SDL_MOUSEWHEEL) { scaleViewport(scaleMouseWheel(event.wheel.y), normalizedElements); - drawFrame(renderer, normalizedElements); } } + drawFrame(renderer, normalizedElements, backgroundColor, screenW, screenH, drawColor, texturize); } // Shutdown SDL_DestroyWindow(window); + SDL_DestroyRenderer(renderer); + SDL_DestroyTexture(gatesTexture); SDL_Quit(); return 0; } diff --git a/src/main.h b/src/main.h index 8af0ddb..f8bc53f 100644 --- a/src/main.h +++ b/src/main.h @@ -11,6 +11,29 @@ #include +enum Type { + NONE = 0, + INPUT, + OUTPUT, + NOT, + AND, + OR, + NAND, + NOR, + DFF +}; + +struct ScreenType { + SDL_Rect textureRect; + + ScreenType(): type(NONE) {} + void setType(Type type); + Type getType() const; + +private: + Type type; +}; + struct NormalizedPoint { float nX; float nY; @@ -18,27 +41,36 @@ struct NormalizedPoint { NormalizedPoint(): nX(0), nY(0) {} }; -struct NormalizedConnection { +struct Connection { unsigned int id; unsigned int startElementId; unsigned int endElementId; + SDL_Color color; std::vector nVertices; std::vector scrVertices; - NormalizedConnection(): id(-1), startElementId(-1), endElementId(-1) {} + Connection(): id(-1), startElementId(-1), endElementId(-1) { + color = {255, 255, 255, 255}; + } void normalizedToScreen(const int screenW, const int screenH); void scale(const float scalingFactor, const int mouseX, const int mouseY); void move(const int dx, const int dy); }; -struct NormalizedElement { +struct Element { unsigned int id; NormalizedPoint nPoint; float nW, nH; SDL_FRect scrRect; - std::vector connections; + SDL_Color outlineColor; + SDL_Color fillColor; + std::vector connections; + ScreenType scrType; - NormalizedElement(): id(-1), nW(0), nH(0) {} + Element(): id(-1), nW(0), nH(0) { + outlineColor = {255, 255, 255, 255}; + fillColor = {0, 0, 0, 255}; + } void normalizedToScreen(const int screenW, const int screenH); void scale(const float scalingFactor, const int mouseX, const int mouseY); void move(const int dx, const int dy); diff --git a/src/netfmt_bench.cpp b/src/netfmt_bench.cpp index f44316b..7963cf0 100644 --- a/src/netfmt_bench.cpp +++ b/src/netfmt_bench.cpp @@ -30,15 +30,15 @@ class BenchNetReader: public lorina::bench_reader { } virtual void on_input(const std::string &name) const override { - UNUSED(getNode(name)); + UNUSED(getNode(name, INPUT)); } virtual void on_output(const std::string &name) const override { - UNUSED(getNode(name)); + UNUSED(getNode(name, OUTPUT)); } virtual void on_dff_input(const std::string &input) const override { - UNUSED(getNode(input)); + UNUSED(getNode(input, DFF)); } virtual void on_dff( @@ -50,9 +50,19 @@ class BenchNetReader: public lorina::bench_reader { const std::vector &inputs, const std::string &output, const std::string &type) const override { - UNUSED(type); - - TreeNode *dst = getNode(output); + Type numType = NONE; + if (type == "NOT") { + numType = NOT; + } else if (type == "AND") { + numType = AND; + } else if (type == "OR") { + numType = OR; + } else if (type == "NAND") { + numType = NAND; + } else if (type == "NOR") { + numType = NOR; + } + TreeNode *dst = getNode(output, numType); for (const std::string &input: inputs) { linkNodes(getNode(input), dst); } @@ -69,14 +79,14 @@ class BenchNetReader: public lorina::bench_reader { dst->pred.push_back(src->id); } - TreeNode *getNode(const std::string &name) const { + TreeNode *getNode(const std::string &name, Type type = NONE) const { Net::Id id; auto it = nodeMap.find(name); if (it != nodeMap.end()) { id = it->second; } else { - id = net.addNode(); + id = net.addNode(type); nodeMap.emplace(name, id); } return net.getNode(id); diff --git a/test/bench.cpp b/test/bench.cpp index 5555aac..cd21a33 100644 --- a/test/bench.cpp +++ b/test/bench.cpp @@ -52,6 +52,7 @@ class bench_statistics_reader : public bench_reader { gate_lines.emplace_back( inputs, output, type ); ++_stats.number_of_lines; + std::cout << type << std::endl; } virtual void on_assign( const std::string& input, const std::string& output ) const override diff --git a/test/test.xml b/test/test.xml index 72d1827..91ea630 100644 --- a/test/test.xml +++ b/test/test.xml @@ -1,34 +1,58 @@ + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + - - - - + + + + + + + +