// dear imgui, v1.66 WIP
// (demo code)

// Message to the person tempted to delete this file when integrating ImGui into their code base:
// Don't do it! Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to.
// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
// During development, you can call ImGui::ShowDemoWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu!
// Removing this file from your project is hindering access to documentation for everyone in your team, likely leading you to poorer usage of the library.
// Note that you can #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h for the same effect.
// If you want to link core ImGui in your final builds but not those demo windows, #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h and those functions will be empty.
// In other situation, when you have ImGui available you probably want this to be available for reference and execution.
// Thank you,
// -Your beloved friend, imgui_demo.cpp (that you won't delete)

// Message to beginner C/C++ programmers about the meaning of the 'static' keyword: in this demo code, we frequently we use 'static' variables inside functions.
// A static variable persist across calls, so it is essentially like a global variable but declared inside the scope of the function.
// We do this as a way to gather code and data in the same place, just to make the demo code faster to read, faster to write, and use less code.
// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant or used in threads.
// This might be a pattern you occasionally want to use in your code, but most of the real data you would be editing is likely to be stored outside your functions.

/*

Index of this file:

// [SECTION] Forward Declarations, Helpers
// [SECTION] Demo Window / ShowDemoWindow()
// [SECTION] Style Editor / ShowStyleEditor()
// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
// [SECTION] Example App: Long Text / ShowExampleAppLongText()
// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()

*/

#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "imgui.h"
#include <ctype.h>          // toupper, isprint
#include <limits.h>         // INT_MIN, INT_MAX
#include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
#include <stdio.h>          // vsnprintf, sscanf, printf
#include <stdlib.h>         // NULL, malloc, free, atoi
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h>         // intptr_t
#else
#include <stdint.h>         // intptr_t
#endif

#ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#define vsnprintf _vsnprintf
#endif
#ifdef __clang__
#pragma clang diagnostic ignored "-Wold-style-cast"             // warning : use of old-style cast                              // yes, they are more terse.
#pragma clang diagnostic ignored "-Wdeprecated-declarations"    // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"   // warning : cast to 'void *' from smaller integer type 'int'
#pragma clang diagnostic ignored "-Wformat-security"            // warning : warning: format string is not a string literal
#pragma clang diagnostic ignored "-Wexit-time-destructors"      // warning : declaration requires an exit-time destructor       // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
#if __has_warning("-Wreserved-id-macro")
#pragma clang diagnostic ignored "-Wreserved-id-macro"          // warning : macro name is a reserved identifier                //
#endif
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"          // warning: cast to pointer from integer of different size
#pragma GCC diagnostic ignored "-Wformat-security"              // warning : format string is not a string literal (potentially insecure)
#pragma GCC diagnostic ignored "-Wdouble-promotion"             // warning: implicit conversion from 'float' to 'double' when passing argument to function
#pragma GCC diagnostic ignored "-Wconversion"                   // warning: conversion to 'xxxx' from 'xxxx' may alter its value
#if (__GNUC__ >= 6)
#pragma GCC diagnostic ignored "-Wmisleading-indentation"       // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
#endif
#endif

// Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n.
#ifdef _WIN32
#define IM_NEWLINE "\r\n"
#else
#define IM_NEWLINE "\n"
#endif

#define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))

//-----------------------------------------------------------------------------
// [SECTION] Forward Declarations, Helpers
//-----------------------------------------------------------------------------

#if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS)   // Obsolete name since 1.53, TEST->DEMO
#define IMGUI_DISABLE_DEMO_WINDOWS
#endif

#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)

// Forward Declarations
static void ShowExampleAppMainMenuBar();
static void ShowExampleAppConsole(bool* p_open);
static void ShowExampleAppLog(bool* p_open);
static void ShowExampleAppLayout(bool* p_open);
static void ShowExampleAppPropertyEditor(bool* p_open);
static void ShowExampleAppLongText(bool* p_open);
static void ShowExampleAppAutoResize(bool* p_open);
static void ShowExampleAppConstrainedResize(bool* p_open);
static void ShowExampleAppSimpleOverlay(bool* p_open);
static void ShowExampleAppWindowTitles(bool* p_open);
static void ShowExampleAppCustomRendering(bool* p_open);
static void ShowExampleMenuFile();

// Helper to display a little (?) mark which shows a tooltip when hovered.
static void ShowHelpMarker(const char* desc)
{
    ImGui::TextDisabled("(?)");
    if (ImGui::IsItemHovered())
    {
        ImGui::BeginTooltip();
        ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
        ImGui::TextUnformatted(desc);
        ImGui::PopTextWrapPos();
        ImGui::EndTooltip();
    }
}

// Helper to display basic user controls.
void ImGui::ShowUserGuide()
{
    ImGui::BulletText("Double-click on title bar to collapse window.");
    ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
    ImGui::BulletText("Click and drag on any empty space to move window.");
    ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
    ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
    if (ImGui::GetIO().FontAllowUserScaling)
        ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
    ImGui::BulletText("Mouse Wheel to scroll.");
    ImGui::BulletText("While editing text:\n");
    ImGui::Indent();
    ImGui::BulletText("Hold SHIFT or use mouse to select text.");
    ImGui::BulletText("CTRL+Left/Right to word jump.");
    ImGui::BulletText("CTRL+A or double-click to select all.");
    ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
    ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
    ImGui::BulletText("ESCAPE to revert.");
    ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
    ImGui::Unindent();
}

//-----------------------------------------------------------------------------
// [SECTION] Demo Window / ShowDemoWindow()
//-----------------------------------------------------------------------------

// Demonstrate most Dear ImGui features (this is big function!)
// You may execute this function to experiment with the UI and understand what it does. You may then search for keywords in the code when you are interested by a specific feature.
void ImGui::ShowDemoWindow(bool* p_open)
{
    // Examples Apps (accessible from the "Examples" menu)
    static bool show_app_main_menu_bar = false;
    static bool show_app_console = false;
    static bool show_app_log = false;
    static bool show_app_layout = false;
    static bool show_app_property_editor = false;
    static bool show_app_long_text = false;
    static bool show_app_auto_resize = false;
    static bool show_app_constrained_resize = false;
    static bool show_app_simple_overlay = false;
    static bool show_app_window_titles = false;
    static bool show_app_custom_rendering = false;

    if (show_app_main_menu_bar)       ShowExampleAppMainMenuBar();
    if (show_app_console)             ShowExampleAppConsole(&show_app_console);
    if (show_app_log)                 ShowExampleAppLog(&show_app_log);
    if (show_app_layout)              ShowExampleAppLayout(&show_app_layout);
    if (show_app_property_editor)     ShowExampleAppPropertyEditor(&show_app_property_editor);
    if (show_app_long_text)           ShowExampleAppLongText(&show_app_long_text);
    if (show_app_auto_resize)         ShowExampleAppAutoResize(&show_app_auto_resize);
    if (show_app_constrained_resize)  ShowExampleAppConstrainedResize(&show_app_constrained_resize);
    if (show_app_simple_overlay)      ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
    if (show_app_window_titles)       ShowExampleAppWindowTitles(&show_app_window_titles);
    if (show_app_custom_rendering)    ShowExampleAppCustomRendering(&show_app_custom_rendering);

    // Dear ImGui Apps (accessible from the "Help" menu)
    static bool show_app_metrics = false;
    static bool show_app_style_editor = false;
    static bool show_app_about = false;

    if (show_app_metrics)             { ImGui::ShowMetricsWindow(&show_app_metrics); }
    if (show_app_style_editor)        { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
    if (show_app_about)
    {
        ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);
        ImGui::Text("Dear ImGui, %s", ImGui::GetVersion());
        ImGui::Separator();
        ImGui::Text("By Omar Cornut and all dear imgui contributors.");
        ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
        ImGui::End();
    }

    // Demonstrate the various window flags. Typically you would just use the default!
    static bool no_titlebar = false;
    static bool no_scrollbar = false;
    static bool no_menu = false;
    static bool no_move = false;
    static bool no_resize = false;
    static bool no_collapse = false;
    static bool no_close = false;
    static bool no_nav = false;
    static bool no_background = false;
    static bool no_bring_to_front = false;
    
    ImGuiWindowFlags window_flags = 0;
    if (no_titlebar)        window_flags |= ImGuiWindowFlags_NoTitleBar;
    if (no_scrollbar)       window_flags |= ImGuiWindowFlags_NoScrollbar;
    if (!no_menu)           window_flags |= ImGuiWindowFlags_MenuBar;
    if (no_move)            window_flags |= ImGuiWindowFlags_NoMove;
    if (no_resize)          window_flags |= ImGuiWindowFlags_NoResize;
    if (no_collapse)        window_flags |= ImGuiWindowFlags_NoCollapse;
    if (no_nav)             window_flags |= ImGuiWindowFlags_NoNav;
    if (no_background)      window_flags |= ImGuiWindowFlags_NoBackground;
    if (no_bring_to_front)  window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
    if (no_close)           p_open = NULL; // Don't pass our bool* to Begin

    // We specify a default position/size in case there's no data in the .ini file. Typically this isn't required! We only do it to make the Demo applications a little more welcoming.
    ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver);
    ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);

    // Main body of the Demo window starts here.
    if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
    {
        // Early out if the window is collapsed, as an optimization.
        ImGui::End();
        return;
    }
    ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);

    // Most "big" widgets share a common width settings by default.
    //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);    // Use 2/3 of the space for widgets and 1/3 for labels (default)
    ImGui::PushItemWidth(ImGui::GetFontSize() * -12);           // Use fixed width for labels (by passing a negative value), the rest goes to widgets. We choose a width proportional to our font size.

    // Menu
    if (ImGui::BeginMenuBar())
    {
        if (ImGui::BeginMenu("Menu"))
        {
            ShowExampleMenuFile();
            ImGui::EndMenu();
        }
        if (ImGui::BeginMenu("Examples"))
        {
            ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
            ImGui::MenuItem("Console", NULL, &show_app_console);
            ImGui::MenuItem("Log", NULL, &show_app_log);
            ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
            ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
            ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
            ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
            ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
            ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
            ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
            ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
            ImGui::EndMenu();
        }
        if (ImGui::BeginMenu("Help"))
        {
            ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
            ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
            ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
            ImGui::EndMenu();
        }
        ImGui::EndMenuBar();
    }

    ImGui::Spacing();
    if (ImGui::CollapsingHeader("Help"))
    {
        ImGui::Text("PROGRAMMER GUIDE:");
        ImGui::BulletText("Please see the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
        ImGui::BulletText("Please see the comments in imgui.cpp.");
        ImGui::BulletText("Please see the examples/ in application.");
        ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
        ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
        ImGui::Separator();

        ImGui::Text("USER GUIDE:");
        ImGui::ShowUserGuide();
    }

    if (ImGui::CollapsingHeader("Configuration"))
    {
        ImGuiIO& io = ImGui::GetIO();

        if (ImGui::TreeNode("Configuration##2"))
        {
            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
            ImGui::SameLine(); ShowHelpMarker("Required back-end to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
            ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
            ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouse);
            if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) // Create a way to restore this flag otherwise we could be stuck completely!
            {
                if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
                {
                    ImGui::SameLine();
                    ImGui::Text("<<PRESS SPACE TO DISABLE>>");
                }
                if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
                    io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
            }
            ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
            ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
            ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
            ImGui::SameLine(); ShowHelpMarker("Set to false to disable blinking cursor, for users who consider it distracting");
            ImGui::Checkbox("io.ConfigResizeWindowsFromEdges [beta]", &io.ConfigResizeWindowsFromEdges);
            ImGui::SameLine(); ShowHelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
            ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
            ImGui::SameLine(); ShowHelpMarker("Instruct Dear ImGui to render a mouse cursor for you. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
            ImGui::TreePop();
            ImGui::Separator();
        }

        if (ImGui::TreeNode("Backend Flags"))
        {
            ImGuiBackendFlags backend_flags = io.BackendFlags; // Make a local copy to avoid modifying the back-end flags.
            ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasGamepad);
            ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasMouseCursors);
            ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasSetMousePos);
            ImGui::TreePop();
            ImGui::Separator();
        }

        if (ImGui::TreeNode("Style"))
        {
            ImGui::ShowStyleEditor();
            ImGui::TreePop();
            ImGui::Separator();
        }

        if (ImGui::TreeNode("Capture/Logging"))
        {
            ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded.");
            ShowHelpMarker("Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
            ImGui::LogButtons();
            ImGui::TextWrapped("You can also call ImGui::LogText() to output directly to the log without a visual output.");
            if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
            {
                ImGui::LogToClipboard();
                ImGui::LogText("Hello, world!");
                ImGui::LogFinish();
            }
            ImGui::TreePop();
        }
    }

    if (ImGui::CollapsingHeader("Window options"))
    {
        ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
        ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
        ImGui::Checkbox("No menu", &no_menu);
        ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
        ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
        ImGui::Checkbox("No collapse", &no_collapse);
        ImGui::Checkbox("No close", &no_close); ImGui::SameLine(150);
        ImGui::Checkbox("No nav", &no_nav); ImGui::SameLine(300);
        ImGui::Checkbox("No background", &no_background);
        ImGui::Checkbox("No bring to front", &no_bring_to_front);
    }

    if (ImGui::CollapsingHeader("Widgets"))
    {
        if (ImGui::TreeNode("Basic"))
        {
            static int clicked = 0;
            if (ImGui::Button("Button"))
                clicked++;
            if (clicked & 1)
            {
                ImGui::SameLine();
                ImGui::Text("Thanks for clicking me!");
            }

            static bool check = true;
            ImGui::Checkbox("checkbox", &check);

            static int e = 0;
            ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
            ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
            ImGui::RadioButton("radio c", &e, 2);

            // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
            for (int i = 0; i < 7; i++)
            {
                if (i > 0) 
                    ImGui::SameLine();
                ImGui::PushID(i);
                ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));
                ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));
                ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));
                ImGui::Button("Click");
                ImGui::PopStyleColor(3);
                ImGui::PopID();
            }

            // Use AlignTextToFramePadding() to align text baseline to the baseline of framed elements (otherwise a Text+SameLine+Button sequence will have the text a little too high by default)
            ImGui::AlignTextToFramePadding();
            ImGui::Text("Hold to repeat:");
            ImGui::SameLine();

            // Arrow buttons with Repeater
            static int counter = 0;
            float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
            ImGui::PushButtonRepeat(true);
            if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
            ImGui::SameLine(0.0f, spacing);
            if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
            ImGui::PopButtonRepeat();
            ImGui::SameLine();
            ImGui::Text("%d", counter);

            ImGui::Text("Hover over me");
            if (ImGui::IsItemHovered())
                ImGui::SetTooltip("I am a tooltip");

            ImGui::SameLine();
            ImGui::Text("- or me");
            if (ImGui::IsItemHovered())
            {
                ImGui::BeginTooltip();
                ImGui::Text("I am a fancy tooltip");
                static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
                ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
                ImGui::EndTooltip();
            }

            ImGui::Separator();

            ImGui::LabelText("label", "Value");

            {
                // Using the _simplified_ one-liner Combo() api here
                // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
                const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
                static int item_current = 0;
                ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
                ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n");
            }

            {
                static char str0[128] = "Hello, world!";
                static int i0 = 123;
                ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
                ImGui::SameLine(); ShowHelpMarker("USER:\nHold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp).");

                ImGui::InputInt("input int", &i0);
                ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n  e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");

                static float f0 = 0.001f;
                ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);

                static double d0 = 999999.00000001;
                ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");

                static float f1 = 1.e10f;
                ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
                ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n  e.g. \"1e+8\" becomes \"100000000\".\n");

                static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
                ImGui::InputFloat3("input float3", vec4a);
            }

            {
                static int i1 = 50, i2 = 42;
                ImGui::DragInt("drag int", &i1, 1);
                ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");

                ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%");

                static float f1=1.00f, f2=0.0067f;
                ImGui::DragFloat("drag float", &f1, 0.005f);
                ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
            }

            {
                static int i1=0;
                ImGui::SliderInt("slider int", &i1, -1, 3);
                ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");

                static float f1=0.123f, f2=0.0f;
                ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
                ImGui::SliderFloat("slider float (curve)", &f2, -10.0f, 10.0f, "%.4f", 2.0f);
                static float angle = 0.0f;
                ImGui::SliderAngle("slider angle", &angle);
            }

            {
                static float col1[3] = { 1.0f,0.0f,0.2f };
                static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
                ImGui::ColorEdit3("color 1", col1);
                ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nClick and hold to use drag and drop.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");

                ImGui::ColorEdit4("color 2", col2);
            }

            {
                // List box
                const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
                static int listbox_item_current = 1;
                ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);

                //static int listbox_item_current2 = 2;
                //ImGui::PushItemWidth(-1);
                //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
                //ImGui::PopItemWidth();
            }

            ImGui::TreePop();
        }

        // Testing ImGuiOnceUponAFrame helper.
        //static ImGuiOnceUponAFrame once;
        //for (int i = 0; i < 5; i++)
        //    if (once)
        //        ImGui::Text("This will be displayed only once.");

        if (ImGui::TreeNode("Trees"))
        {
            if (ImGui::TreeNode("Basic trees"))
            {
                for (int i = 0; i < 5; i++)
                    if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
                    {
                        ImGui::Text("blah blah");
                        ImGui::SameLine();
                        if (ImGui::SmallButton("button")) { };
                        ImGui::TreePop();
                    }
                ImGui::TreePop();
            }

            if (ImGui::TreeNode("Advanced, with Selectable nodes"))
            {
                ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
                static bool align_label_with_current_x_position = false;
                ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
                ImGui::Text("Hello!");
                if (align_label_with_current_x_position)
                    ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());

                static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
                int node_clicked = -1;                // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.
                ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.
                for (int i = 0; i < 6; i++)
                {
                    // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
                    ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
                    if (i < 3)
                    {
                        // Node
                        bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
                        if (ImGui::IsItemClicked())
                            node_clicked = i;
                        if (node_open)
                        {
                            ImGui::Text("Blah blah\nBlah Blah");
                            ImGui::TreePop();
                        }
                    }
                    else
                    {
                        // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text().
                        node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
                        ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
                        if (ImGui::IsItemClicked())
                            node_clicked = i;
                    }
                }
                if (node_clicked != -1)
                {
                    // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
                    if (ImGui::GetIO().KeyCtrl)
                        selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle
                    else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection
                        selection_mask = (1 << node_clicked);           // Click to single-select
                }
                ImGui::PopStyleVar();
                if (align_label_with_current_x_position)
                    ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
                ImGui::TreePop();
            }
            ImGui::TreePop();
        }

        if (ImGui::TreeNode("Collapsing Headers"))
        {
            static bool closable_group = true;
            ImGui::Checkbox("Enable extra group", &closable_group);
            if (ImGui::CollapsingHeader("Header"))
            {
                ImGui::Text("IsItemHovered: %d", IsItemHovered());
                for (int i = 0; i < 5; i++)
                    ImGui::Text("Some content %d", i);
            }
            if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
            {
                ImGui::Text("IsItemHovered: %d", IsItemHovered());
                for (int i = 0; i < 5; i++)
                    ImGui::Text("More content %d", i);
            }
            ImGui::TreePop();
        }

        if (ImGui::TreeNode("Bullets"))
        {
            ImGui::BulletText("Bullet point 1");
            ImGui::BulletText("Bullet point 2\nOn multiple lines");
            ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
            ImGui::Bullet(); ImGui::SmallButton("Button");
            ImGui::TreePop();
        }

        if (ImGui::TreeNode("Text"))
        {
            if (ImGui::TreeNode("Colored Text"))
            {
                // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
                ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
                ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
                ImGui::TextDisabled("Disabled");
                ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
                ImGui::TreePop();
            }

            if (ImGui::TreeNode("Word Wrapping"))
            {
                // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
                ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages.");
                ImGui::Spacing();

                static float wrap_width = 200.0f;
                ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");

                ImGui::Text("Test paragraph 1:");
                ImVec2 pos = ImGui::GetCursorScreenPos();
                ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));
                ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
                ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps o<style>pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="k">\section</span><span class="nb">{</span>Introduction to Yosys<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>
<span class="k">\sectionpage</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\iffalse</span>
<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Representations of (digital) Circuits<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[t]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
	<span class="k">\item</span> Graphical
		<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
			<span class="k">\item</span> <span class="k">\alert</span>&lt;1&gt;<span class="nb">{</span>Schematic Diagram<span class="nb">}</span>
			<span class="k">\item</span> <span class="k">\alert</span>&lt;2&gt;<span class="nb">{</span>Physical Layout<span class="nb">}</span>
		<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
	<span class="k">\bigskip</span>
	<span class="k">\item</span> Non-graphical
		<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
			<span class="k">\item</span> <span class="k">\alert</span>&lt;3&gt;<span class="nb">{</span>Netlists<span class="nb">}</span>
			<span class="k">\item</span> <span class="k">\alert</span>&lt;4&gt;<span class="nb">{</span>Hardware Description Languages (HDLs)<span class="nb">}</span>
		<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\bigskip</span>
<span class="k">\begin</span><span class="nb">{</span>block<span class="nb">}{</span>Definition:
<span class="k">\only</span>&lt;1&gt;<span class="nb">{</span>Schematic Diagram<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;2&gt;<span class="nb">{</span>Physical Layout<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;3&gt;<span class="nb">{</span>Netlists<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;4&gt;<span class="nb">{</span>Hardware Description Languages (HDLs)<span class="nb">}}</span>
<span class="k">\only</span>&lt;1&gt;<span class="nb">{</span>
	Graphical representation of the circuit topology. Circuit elements
	are represented by symbols and electrical connections by lines. The geometric
	layout is for readability only.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;2&gt;<span class="nb">{</span>
	The actual physical geometry of the device (PCB or ASIC manufacturing masks).
	This is the final product of the design process.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;3&gt;<span class="nb">{</span>
	A list of circuit elements and a list of connections. This is the raw circuit
	topology.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;4&gt;<span class="nb">{</span>
	Computer languages (like programming languages) that can be used to describe
	circuits. HDLs are much more powerful in describing huge circuits than
	schematic diagrams.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\end</span><span class="nb">{</span>block<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>
<span class="k">\fi</span>

<span class="k">\subsection</span><span class="nb">{</span>Levels of Abstraction for Digital Circuits<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[t]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
	<span class="k">\item</span> <span class="k">\alert</span>&lt;1&gt;<span class="nb">{</span>System Level<span class="nb">}</span>
	<span class="k">\item</span> <span class="k">\alert</span>&lt;2&gt;<span class="nb">{</span>High Level<span class="nb">}</span>
	<span class="k">\item</span> <span class="k">\alert</span>&lt;3&gt;<span class="nb">{</span>Behavioral Level<span class="nb">}</span>
	<span class="k">\item</span> <span class="k">\alert</span>&lt;4&gt;<span class="nb">{</span>Register-Transfer Level (RTL)<span class="nb">}</span>
	<span class="k">\item</span> <span class="k">\alert</span>&lt;5&gt;<span class="nb">{</span>Logical Gate Level<span class="nb">}</span>
	<span class="k">\item</span> <span class="k">\alert</span>&lt;6&gt;<span class="nb">{</span>Physical Gate Level<span class="nb">}</span>
	<span class="k">\item</span> <span class="k">\alert</span>&lt;7&gt;<span class="nb">{</span>Switch Level<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\bigskip</span>
<span class="k">\begin</span><span class="nb">{</span>block<span class="nb">}{</span>Definition:
<span class="k">\only</span>&lt;1&gt;<span class="nb">{</span>System Level<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;2&gt;<span class="nb">{</span>High Level<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;3&gt;<span class="nb">{</span>Behavioral Level<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;4&gt;<span class="nb">{</span>Register-Transfer Level (RTL)<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;5&gt;<span class="nb">{</span>Logical Gate Level<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;6&gt;<span class="nb">{</span>Physical Gate Level<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;7&gt;<span class="nb">{</span>Switch Level<span class="nb">}}</span>
<span class="k">\only</span>&lt;1&gt;<span class="nb">{</span>
	Overall view of the circuit. E.g. block-diagrams or instruction-set architecture descriptions.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;2&gt;<span class="nb">{</span>
	Functional implementation of circuit in high-level programming language (C, C++, SystemC, Matlab, Python, etc.).
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;3&gt;<span class="nb">{</span>
	Cycle-accurate description of circuit in hardware description language (Verilog, VHDL, etc.).
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;4&gt;<span class="nb">{</span>
	List of registers (flip-flops) and logic functions that calculate the next state from the previous one. Usually
	a netlist utilizing high-level cells such as adders, multipliers, multiplexer, etc.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;5&gt;<span class="nb">{</span>
	Netlist of single-bit registers and basic logic gates (such as AND, OR,
	NOT, etc.). Popular form: And-Inverter-Graphs (AIGs) with pairs of primary
	inputs and outputs for each register bit.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;6&gt;<span class="nb">{</span>
	Netlist of cells that actually are available on the target architecture
	(such as CMOS gates in an ASIC or LUTs in an FPGA). Optimized for
	area, power, and/or speed (static timing or number of logic levels).
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;7&gt;<span class="nb">{</span>
	Netlist of individual transistors.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\end</span><span class="nb">{</span>block<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Digital Circuit Synthesis<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
	Synthesis Tools (such as Yosys) can transform HDL code to circuits:

	<span class="k">\bigskip</span>
	<span class="k">\begin</span><span class="nb">{</span>center<span class="nb">}</span>
	<span class="k">\begin</span><span class="nb">{</span>tikzpicture<span class="nb">}</span>[scale=0.8, every node/.style=<span class="nb">{</span>transform shape<span class="nb">}</span>]
			<span class="k">\tikzstyle</span><span class="nb">{</span>lvl<span class="nb">}</span> = [draw, fill=MyBlue, rectangle, minimum height=2em, minimum width=15em]
			<span class="k">\node</span><span class="na">[lvl]</span> (sys) <span class="nb">{</span>System Level<span class="nb">}</span>;
			<span class="k">\node</span><span class="na">[lvl]</span> (hl) [below of=sys] <span class="nb">{</span>High Level<span class="nb">}</span>;
			<span class="k">\node</span><span class="na">[lvl]</span> (beh) [below of=hl] <span class="nb">{</span>Behavioral Level<span class="nb">}</span>;
			<span class="k">\node</span><span class="na">[lvl]</span> (rtl) [below of=beh] <span class="nb">{</span>Register-Transfer Level (RTL)<span class="nb">}</span>;
			<span class="k">\node</span><span class="na">[lvl]</span> (lg) [below of=rtl] <span class="nb">{</span>Logical Gate Level<span class="nb">}</span>;
			<span class="k">\node</span><span class="na">[lvl]</span> (pg) [below of=lg] <span class="nb">{</span>Physical Gate Level<span class="nb">}</span>;
			<span class="k">\node</span><span class="na">[lvl]</span> (sw) [below of=pg] <span class="nb">{</span>Switch Level<span class="nb">}</span>;

			<span class="k">\draw</span><span class="na">[dotted]</span> (sys.east)  -- ++(1,0) coordinate (sysx);
			<span class="k">\draw</span><span class="na">[dotted]</span> (hl.east)  -- ++(1,0) coordinate (hlx);
			<span class="k">\draw</span><span class="na">[dotted]</span> (beh.east) -- ++(1,0) coordinate (behx);
			<span class="k">\draw</span><span class="na">[dotted]</span> (rtl.east) -- ++(1,0) coordinate (rtlx);
			<span class="k">\draw</span><span class="na">[dotted]</span> (lg.east)  -- ++(1,0) coordinate (lgx);
			<span class="k">\draw</span><span class="na">[dotted]</span> (pg.east)  -- ++(1,0) coordinate (pgx);
			<span class="k">\draw</span><span class="na">[dotted]</span> (sw.east)  -- ++(1,0) coordinate (swx);

			<span class="k">\draw</span><span class="na">[gray,|-&gt;]</span> (sysx) -- node[right] <span class="nb">{</span>System Design<span class="nb">}</span> (hlx);
			<span class="k">\draw</span><span class="na">[|-&gt;|]</span> (hlx) -- node[right] <span class="nb">{</span>High Level Synthesis (HLS)<span class="nb">}</span> (behx);
			<span class="k">\draw</span><span class="na">[-&gt;|]</span> (behx) -- node[right] <span class="nb">{</span>Behavioral Synthesis<span class="nb">}</span> (rtlx);
			<span class="k">\draw</span><span class="na">[-&gt;|]</span> (rtlx) -- node[right] <span class="nb">{</span>RTL Synthesis<span class="nb">}</span> (lgx);
			<span class="k">\draw</span><span class="na">[-&gt;|]</span> (lgx) -- node[right] <span class="nb">{</span>Logic Synthesis<span class="nb">}</span> (pgx);
			<span class="k">\draw</span><span class="na">[gray,-&gt;|]</span> (pgx) -- node[right] <span class="nb">{</span>Cell Library<span class="nb">}</span> (swx);

			<span class="k">\draw</span><span class="na">[dotted]</span> (behx) -- ++(4,0) coordinate (a);
			<span class="k">\draw</span><span class="na">[dotted]</span> (pgx) -- ++(4,0) coordinate (b);
			<span class="k">\draw</span><span class="na">[|-&gt;|]</span> (a) -- node[right] <span class="nb">{</span>Yosys<span class="nb">}</span> (b);
	<span class="k">\end</span><span class="nb">{</span>tikzpicture<span class="nb">}</span>
	<span class="k">\end</span><span class="nb">{</span>center<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>What Yosys can and can&#39;t do<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>

Things Yosys can do:
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Read and process (most of) modern Verilog-2005 code.
<span class="k">\item</span> Perform all kinds of operations on netlist (RTL, Logic, Gate).
<span class="k">\item</span> Perform logic optimizations and gate mapping with ABC<span class="k">\footnote</span><span class="na">[frame]</span><span class="nb">{</span><span class="k">\url</span><span class="nb">{</span>http://www.eecs.berkeley.edu/~alanmi/abc/<span class="nb">}}</span>.
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

<span class="k">\bigskip</span>
Things Yosys can&#39;t do:
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Process high-level languages such as C/C++/SystemC.
<span class="k">\item</span> Create physical layouts (place<span class="k">\&amp;</span>route).
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

<span class="k">\bigskip</span>
A typical flow combines Yosys with with a low-level implementation tool, such
as Qflow<span class="k">\footnote</span><span class="na">[frame]</span><span class="nb">{</span><span class="k">\url</span><span class="nb">{</span>http://opencircuitdesign.com/qflow/<span class="nb">}}</span> for ASIC designs.

<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Yosys Data- and Control-Flow<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
	A (usually short) synthesis script controls Yosys.

	This scripts contain three types of commands:
	<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
	<span class="k">\item</span> <span class="nb">{</span><span class="k">\bf</span> Frontends<span class="nb">}</span>, that read input files (usually Verilog).
	<span class="k">\item</span> <span class="nb">{</span><span class="k">\bf</span> Passes<span class="nb">}</span>, that perform transformations on the design in memory.
	<span class="k">\item</span> <span class="nb">{</span><span class="k">\bf</span> Backends<span class="nb">}</span>, that write the design in memory to a file (various formats are available: Verilog, BLIF, EDIF, SPICE, BTOR, <span class="k">\dots</span>).
	<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

	<span class="k">\bigskip</span>
	<span class="k">\begin</span><span class="nb">{</span>center<span class="nb">}</span>
	<span class="k">\begin</span><span class="nb">{</span>tikzpicture<span class="nb">}</span>[scale=0.6, every node/.style=<span class="nb">{</span>transform shape<span class="nb">}</span>]
		<span class="k">\path</span> (-1.5,3) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-latex]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">0</span><span class="nb">,</span><span class="o">-</span><span class="m">1</span><span class="nb">.</span><span class="m">5</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) -- ++(1,0);
		<span class="k">\draw</span><span class="na">[fill=orange!10]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">1</span><span class="nb">,</span><span class="o">-</span><span class="m">3</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) rectangle node[rotate=90] <span class="nb">{</span>Frontend<span class="nb">}</span> ++(1,3) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-latex]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">0</span><span class="nb">,</span><span class="o">-</span><span class="m">1</span><span class="nb">.</span><span class="m">5</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) -- ++(1,0);
		<span class="k">\draw</span><span class="na">[fill=green!10]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">1</span><span class="nb">,</span><span class="o">-</span><span class="m">3</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) rectangle node[rotate=90] <span class="nb">{</span>Pass<span class="nb">}</span> ++(1,3) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-latex]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">0</span><span class="nb">,</span><span class="o">-</span><span class="m">1</span><span class="nb">.</span><span class="m">5</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) -- ++(1,0);
		<span class="k">\draw</span><span class="na">[fill=green!10]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">1</span><span class="nb">,</span><span class="o">-</span><span class="m">3</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) rectangle node[rotate=90] <span class="nb">{</span>Pass<span class="nb">}</span> ++(1,3) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-latex]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">0</span><span class="nb">,</span><span class="o">-</span><span class="m">1</span><span class="nb">.</span><span class="m">5</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) -- ++(1,0);
		<span class="k">\draw</span><span class="na">[fill=green!10]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">1</span><span class="nb">,</span><span class="o">-</span><span class="m">3</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) rectangle node[rotate=90] <span class="nb">{</span>Pass<span class="nb">}</span> ++(1,3) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-latex]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">0</span><span class="nb">,</span><span class="o">-</span><span class="m">1</span><span class="nb">.</span><span class="m">5</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) -- ++(1,0);
		<span class="k">\draw</span><span class="na">[fill=orange!10]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">1</span><span class="nb">,</span><span class="o">-</span><span class="m">3</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) rectangle node[rotate=90] <span class="nb">{</span>Backend<span class="nb">}</span> ++(1,3) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-latex]</span> (<span class="s">$</span><span class="nb"> </span><span class="o">(</span><span class="nb">cursor</span><span class="o">)</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="o">(</span><span class="m">0</span><span class="nb">,</span><span class="o">-</span><span class="m">1</span><span class="nb">.</span><span class="m">5</span><span class="o">)</span><span class="nb"> </span><span class="s">$</span>) -- ++(1,0);

		<span class="k">\path</span> (-3,-0.5) coordinate (cursor);
		<span class="k">\draw</span> (cursor) -- node[below] <span class="nb">{</span>HDL<span class="nb">}</span> ++(3,0) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[|-|]</span> (cursor) -- node[below] <span class="nb">{</span>Internal Format (RTLIL)<span class="nb">}</span> ++(8,0) coordinate (cursor);
		<span class="k">\draw</span> (cursor) -- node[below] <span class="nb">{</span>Netlist<span class="nb">}</span> ++(3,0);

		<span class="k">\path</span> (-3,3.5) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-]</span> (cursor) -- node[above] <span class="nb">{</span>High-Level<span class="nb">}</span> ++(3,0) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-]</span> (cursor) -- ++(8,0) coordinate (cursor);
		<span class="k">\draw</span><span class="na">[-&gt;]</span> (cursor) -- node[above] <span class="nb">{</span>Low-Level<span class="nb">}</span> ++(3,0);
	<span class="k">\end</span><span class="nb">{</span>tikzpicture<span class="nb">}</span>
	<span class="k">\end</span><span class="nb">{</span>center<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Program Components and Data Formats<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
	<span class="k">\begin</span><span class="nb">{</span>center<span class="nb">}</span>
	<span class="k">\begin</span><span class="nb">{</span>tikzpicture<span class="nb">}</span>[scale=0.6, every node/.style=<span class="nb">{</span>transform shape<span class="nb">}</span>]
		<span class="k">\tikzstyle</span><span class="nb">{</span>process<span class="nb">}</span> = [draw, fill=green!10, rectangle, minimum height=3em, minimum width=10em, node distance=15em]
		<span class="k">\tikzstyle</span><span class="nb">{</span>data<span class="nb">}</span> = [draw, fill=blue!10, ellipse, minimum height=3em, minimum width=7em, node distance=15em]
		<span class="k">\node</span><span class="na">[process]</span> (vlog) <span class="nb">{</span>Verilog Frontend<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[process, dashed, fill=green!5]</span> (vhdl) [right of=vlog] <span class="nb">{</span>VHDL Frontend<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[process]</span> (ilang) [right of=vhdl] <span class="nb">{</span>Other Frontends<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[data]</span> (ast) [below of=vlog, node distance=5em, xshift=7.5em] <span class="nb">{</span>AST<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[process]</span> (astfe) [below of=ast, node distance=5em] <span class="nb">{</span>AST Frontend<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[data]</span> (rtlil) [below of=astfe, node distance=5em, xshift=7.5em] <span class="nb">{</span>RTLIL<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[process]</span> (pass) [right of=rtlil, node distance=5em, xshift=7.5em] <span class="nb">{</span>Passes<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[process]</span> (vlbe) [below of=rtlil, node distance=7em, xshift=-13em] <span class="nb">{</span>Verilog Backend<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[process]</span> (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] <span class="nb">{</span>RTLIL Backend<span class="nb">}</span>;
		<span class="k">\node</span><span class="na">[process, fill=green!5]</span> (otherbe) [below of=rtlil, node distance=7em, xshift=+13em] <span class="nb">{</span>Other Backends<span class="nb">}</span>;

		<span class="k">\draw</span><span class="na">[-latex]</span> (vlog) -- (ast);
		<span class="k">\draw</span><span class="na">[-latex]</span> (vhdl) -- (ast);
		<span class="k">\draw</span><span class="na">[-latex]</span> (ast) -- (astfe);
		<span class="k">\draw</span><span class="na">[-latex]</span> (astfe) -- (rtlil);
		<span class="k">\draw</span><span class="na">[-latex]</span> (ilang) -- (rtlil);
		<span class="k">\draw</span><span class="na">[latex-latex]</span> (rtlil) -- (pass);
		<span class="k">\draw</span><span class="na">[-latex]</span> (rtlil) -- (vlbe);
		<span class="k">\draw</span><span class="na">[-latex]</span> (rtlil) -- (ilangbe);
		<span class="k">\draw</span><span class="na">[-latex]</span> (rtlil) -- (otherbe);
	<span class="k">\end</span><span class="nb">{</span>tikzpicture<span class="nb">}</span>
	<span class="k">\end</span><span class="nb">{</span>center<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Example Project<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[t]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">}</span>
The following slides cover an example project. This project contains three files:
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> A simple ASIC synthesis script
<span class="k">\item</span> A digital design written in Verilog
<span class="k">\item</span> A simple CMOS cell library
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\vfill</span>
Direct link to the files: <span class="k">\\</span> <span class="k">\footnotesize</span>
<span class="k">\url</span><span class="nb">{</span>https://github.com/YosysHQ/yosys/tree/master/manual/PRESENTATION<span class="nb">_</span>Intro<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[t]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- Synthesis Script<span class="nb">}</span>

<span class="k">\setbeamercolor</span><span class="nb">{</span>alerted text<span class="nb">}{</span>fg=white,bg=red<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>minipage<span class="nb">}</span>[t]<span class="nb">{</span>6cm<span class="nb">}</span>
<span class="k">\tt\scriptsize</span>
<span class="nb">{</span><span class="k">\color</span><span class="nb">{</span>YosysGreen<span class="nb">}</span><span class="k">\#</span> read design<span class="nb">}</span><span class="k">\\</span>
<span class="k">\boxalert</span>&lt;1&gt;<span class="nb">{</span>read<span class="k">\_</span>verilog counter.v<span class="nb">}</span><span class="k">\\</span>
<span class="k">\boxalert</span>&lt;2&gt;<span class="nb">{</span>hierarchy -check -top counter<span class="nb">}</span>

<span class="k">\medskip</span>
<span class="nb">{</span><span class="k">\color</span><span class="nb">{</span>YosysGreen<span class="nb">}</span><span class="k">\#</span> the high-level stuff<span class="nb">}</span><span class="k">\\</span>
<span class="k">\boxalert</span>&lt;3&gt;<span class="nb">{</span>proc<span class="nb">}</span>; <span class="k">\boxalert</span>&lt;4&gt;<span class="nb">{</span>opt<span class="nb">}</span>; <span class="k">\boxalert</span>&lt;5&gt;<span class="nb">{</span>fsm<span class="nb">}</span>; <span class="k">\boxalert</span>&lt;6&gt;<span class="nb">{</span>opt<span class="nb">}</span>; <span class="k">\boxalert</span>&lt;7&gt;<span class="nb">{</span>memory<span class="nb">}</span>; <span class="k">\boxalert</span>&lt;8&gt;<span class="nb">{</span>opt<span class="nb">}</span>

<span class="k">\medskip</span>
<span class="nb">{</span><span class="k">\color</span><span class="nb">{</span>YosysGreen<span class="nb">}</span><span class="k">\#</span> mapping to internal cell library<span class="nb">}</span><span class="k">\\</span>
<span class="k">\boxalert</span>&lt;9&gt;<span class="nb">{</span>techmap<span class="nb">}</span>; <span class="k">\boxalert</span>&lt;10&gt;<span class="nb">{</span>opt<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>minipage<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>minipage<span class="nb">}</span>[t]<span class="nb">{</span>5cm<span class="nb">}</span>
<span class="k">\tt\scriptsize</span>
<span class="nb">{</span><span class="k">\color</span><span class="nb">{</span>YosysGreen<span class="nb">}</span><span class="k">\#</span> mapping flip-flops to mycells.lib<span class="nb">}</span><span class="k">\\</span>
<span class="k">\boxalert</span>&lt;11&gt;<span class="nb">{</span>dfflibmap -liberty mycells.lib<span class="nb">}</span>

<span class="k">\medskip</span>
<span class="nb">{</span><span class="k">\color</span><span class="nb">{</span>YosysGreen<span class="nb">}</span><span class="k">\#</span> mapping logic to mycells.lib<span class="nb">}</span><span class="k">\\</span>
<span class="k">\boxalert</span>&lt;12&gt;<span class="nb">{</span>abc -liberty mycells.lib<span class="nb">}</span>

<span class="k">\medskip</span>
<span class="nb">{</span><span class="k">\color</span><span class="nb">{</span>YosysGreen<span class="nb">}</span><span class="k">\#</span> cleanup<span class="nb">}</span><span class="k">\\</span>
<span class="k">\boxalert</span>&lt;13&gt;<span class="nb">{</span>clean<span class="nb">}</span>

<span class="k">\medskip</span>
<span class="nb">{</span><span class="k">\color</span><span class="nb">{</span>YosysGreen<span class="nb">}</span><span class="k">\#</span> write synthesized design<span class="nb">}</span><span class="k">\\</span>
<span class="k">\boxalert</span>&lt;14&gt;<span class="nb">{</span>write<span class="k">\_</span>verilog synth.v<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>minipage<span class="nb">}</span>

<span class="k">\vskip</span>1cm

<span class="k">\begin</span><span class="nb">{</span>block<span class="nb">}{</span>Command: <span class="k">\tt</span>
<span class="k">\only</span>&lt;1&gt;<span class="nb">{</span>read<span class="k">\_</span>verilog counter.v<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;2&gt;<span class="nb">{</span>hierarchy -check -top counter<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;3&gt;<span class="nb">{</span>proc<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;4&gt;<span class="nb">{</span>opt<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;5&gt;<span class="nb">{</span>fsm<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;6&gt;<span class="nb">{</span>opt<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;7&gt;<span class="nb">{</span>memory<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;8&gt;<span class="nb">{</span>opt<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;9&gt;<span class="nb">{</span>techmap<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;10&gt;<span class="nb">{</span>opt<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;11&gt;<span class="nb">{</span>dfflibmap -liberty mycells.lib<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;12&gt;<span class="nb">{</span>abc -liberty mycells.lib<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;13&gt;<span class="nb">{</span>clean<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;14&gt;<span class="nb">{</span>write<span class="k">\_</span>verilog synth.v<span class="nb">}}</span>
<span class="k">\only</span>&lt;1&gt;<span class="nb">{</span>
	Read Verilog source file and convert to internal representation.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;2&gt;<span class="nb">{</span>
	Elaborate the design hierarchy. Should always be the first
	command after reading the design. Can re-run AST front-end.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;3&gt;<span class="nb">{</span>
	Convert ``processes&#39;&#39; (the internal representation of behavioral
	Verilog code) into multiplexers and registers.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;4&gt;<span class="nb">{</span>
	Perform some basic optimizations and cleanups.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;5&gt;<span class="nb">{</span>
	Analyze and optimize finite state machines.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;6&gt;<span class="nb">{</span>
	Perform some basic optimizations and cleanups.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;7&gt;<span class="nb">{</span>
	Analyze memories and create circuits to implement them.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;8&gt;<span class="nb">{</span>
	Perform some basic optimizations and cleanups.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;9&gt;<span class="nb">{</span>
	Map coarse-grain RTL cells (adders, etc.) to fine-grain
	logic gates (AND, OR, NOT, etc.).
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;10&gt;<span class="nb">{</span>
	Perform some basic optimizations and cleanups.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;11&gt;<span class="nb">{</span>
	Map registers to available hardware flip-flops.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;12&gt;<span class="nb">{</span>
	Map logic to available hardware gates.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;13&gt;<span class="nb">{</span>
	Clean up the design (just the last step of <span class="nb">{</span><span class="k">\tt</span> opt<span class="nb">}</span>).
<span class="nb">}</span><span class="c">%</span>
<span class="k">\only</span>&lt;14&gt;<span class="nb">{</span>
	Write final synthesis result to output file.
<span class="nb">}</span><span class="c">%</span>
<span class="k">\end</span><span class="nb">{</span>block<span class="nb">}</span>

<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- Verilog Source: <span class="k">\tt</span> counter.v<span class="nb">}</span>
<span class="k">\lstinputlisting</span><span class="na">[xleftmargin=1cm, language=Verilog]</span><span class="nb">{</span>PRESENTATION<span class="nb">_</span>Intro/counter.v<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- Cell Library: <span class="k">\tt</span> mycells.lib<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>columns<span class="nb">}</span>
<span class="k">\column</span><span class="na">[t]</span><span class="nb">{</span>5cm<span class="nb">}</span>
<span class="k">\lstinputlisting</span><span class="na">[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=liberty, lastline=20]</span><span class="nb">{</span>PRESENTATION<span class="nb">_</span>Intro/mycells.lib<span class="nb">}</span>
<span class="k">\column</span><span class="na">[t]</span><span class="nb">{</span>5cm<span class="nb">}</span>
<span class="k">\lstinputlisting</span><span class="na">[basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=liberty, firstline=21]</span><span class="nb">{</span>PRESENTATION<span class="nb">_</span>Intro/mycells.lib<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>columns<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Running the Synthesis Script<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[t, fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- Step 1/4<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>verbatim<span class="nb">}</span>
read<span class="nb">_</span>verilog counter.v
hierarchy -check -top counter
<span class="k">\end</span><span class="nb">{</span>verbatim<span class="nb">}</span>

<span class="k">\vfill</span>
<span class="k">\includegraphics</span><span class="na">[width=\linewidth,trim=0 0cm 0 0cm]</span><span class="nb">{</span>PRESENTATION<span class="nb">_</span>Intro/counter<span class="nb">_</span>00.pdf<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[t, fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- Step 2/4<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>verbatim<span class="nb">}</span>
proc; opt; fsm; opt; memory; opt
<span class="k">\end</span><span class="nb">{</span>verbatim<span class="nb">}</span>

<span class="k">\vfill</span>
<span class="k">\includegraphics</span><span class="na">[width=\linewidth,trim=0 0cm 0 0cm]</span><span class="nb">{</span>PRESENTATION<span class="nb">_</span>Intro/counter<span class="nb">_</span>01.pdf<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[t, fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- Step 3/4<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>verbatim<span class="nb">}</span>
techmap; opt
<span class="k">\end</span><span class="nb">{</span>verbatim<span class="nb">}</span>

<span class="k">\vfill</span>
<span class="k">\includegraphics</span><span class="na">[width=\linewidth,trim=0 0cm 0 2cm]</span><span class="nb">{</span>PRESENTATION<span class="nb">_</span>Intro/counter<span class="nb">_</span>02.pdf<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[t, fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- Step 4/4<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>verbatim<span class="nb">}</span>
dfflibmap -liberty mycells.lib
abc -liberty mycells.lib
clean
<span class="k">\end</span><span class="nb">{</span>verbatim<span class="nb">}</span>

<span class="k">\vfill\hfil</span>
<span class="k">\includegraphics</span><span class="na">[width=10cm,trim=0 0cm 0 0cm]</span><span class="nb">{</span>PRESENTATION<span class="nb">_</span>Intro/counter<span class="nb">_</span>03.pdf<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>The synth command<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}}</span>
Yosys contains a default (recommended example) synthesis script in form of the
<span class="nb">{</span><span class="k">\tt</span> synth<span class="nb">}</span> command. The following commands are executed by this synthesis command:

<span class="k">\begin</span><span class="nb">{</span>columns<span class="nb">}</span>
<span class="k">\column</span><span class="na">[t]</span><span class="nb">{</span>5cm<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
begin:
    hierarchy -check [-top &lt;top&gt;]

coarse:
    proc
    opt
    wreduce
    alumacc
    share
    opt
    fsm
    opt -fast
    memory -nomap
    opt<span class="nb">_</span>clean
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>
<span class="k">\column</span><span class="na">[t]</span><span class="nb">{</span>5cm<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
fine:
    opt -fast -full
    memory<span class="nb">_</span>map
    opt -full
    techmap
    opt -fast

abc:
    abc -fast
    opt -fast
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>columns<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Yosys Commands<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> 1/3 <span class="k">\hspace</span><span class="nb">{</span>0pt plus 1 filll<span class="nb">}</span> (excerpt)<span class="nb">}</span>
Command reference:
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Use ``<span class="nb">{</span><span class="k">\tt</span> help<span class="nb">}</span>&#39;&#39; for a command list and ``<span class="nb">{</span><span class="k">\tt</span> help <span class="k">\it</span> command<span class="nb">}</span>&#39;&#39; for details.
<span class="k">\item</span> Or run ``<span class="nb">{</span><span class="k">\tt</span> yosys -H<span class="nb">}</span>&#39;&#39; or ``<span class="nb">{</span><span class="k">\tt</span> yosys -h <span class="k">\it</span> command<span class="nb">}</span>&#39;&#39;.
<span class="k">\item</span> Or go to <span class="k">\url</span><span class="nb">{</span>https://yosyshq.net/yosys/documentation.html<span class="nb">}</span>.
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

<span class="k">\bigskip</span>
Commands for design navigation and investigation:
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
    cd                   # a shortcut for &#39;select -module &lt;name&gt;&#39;
    ls                   # list modules or objects in modules
    dump                 # print parts of the design in RTLIL format
    show                 # generate schematics using graphviz
    select               # modify and view the list of selected objects
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>

<span class="k">\bigskip</span>
Commands for executing scripts or entering interactive mode:
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
    shell                # enter interactive command mode
    history              # show last interactive commands
    script               # execute commands from script file
    tcl                  # execute a TCL script file
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> 2/3 <span class="k">\hspace</span><span class="nb">{</span>0pt plus 1 filll<span class="nb">}</span> (excerpt)<span class="nb">}</span>
Commands for reading and elaborating the design:
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
    read<span class="nb">_</span>rtlil           # read modules from RTLIL file
    read<span class="nb">_</span>verilog         # read modules from Verilog file
    hierarchy            # check, expand and clean up design hierarchy
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>

<span class="k">\bigskip</span>
Commands for high-level synthesis:
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
    proc                 # translate processes to netlists
    fsm                  # extract and optimize finite state machines
    memory               # translate memories to basic cells
    opt                  # perform simple optimizations
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>

<span class="k">\bigskip</span>
Commands for technology mapping:
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
    techmap              # generic technology mapper
    abc                  # use ABC for technology mapping
    dfflibmap            # technology mapping of flip-flops
    hilomap              # technology mapping of constant hi- and/or lo-drivers
    iopadmap             # technology mapping of i/o pads (or buffers)
    flatten              # flatten design
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> 3/3 <span class="k">\hspace</span><span class="nb">{</span>0pt plus 1 filll<span class="nb">}</span> (excerpt)<span class="nb">}</span>
Commands for writing the results:
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
    write<span class="nb">_</span>blif           # write design to BLIF file
    write<span class="nb">_</span>btor           # write design to BTOR file
    write<span class="nb">_</span>edif           # write design to EDIF netlist file
    write<span class="nb">_</span>rtlil          # write design to RTLIL file
    write<span class="nb">_</span>spice          # write design to SPICE netlist file
    write<span class="nb">_</span>verilog        # write design to Verilog file
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>

<span class="k">\bigskip</span>
Script-Commands for standard synthesis tasks:
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
    synth                # generic synthesis script
    synth<span class="nb">_</span>xilinx         # synthesis for Xilinx FPGAs
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>

<span class="k">\bigskip</span>
Commands for model checking:
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=ys]
    sat                  # solve a SAT problem in the circuit
    miter                # automatically create a miter circuit
    scc                  # detect strongly connected components (logic loops)
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>

<span class="k">\bigskip</span>
... and many many more.
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>More Verilog Examples<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> 1/3<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=Verilog]
module detectprime(a, y);
    input [4:0] a;
    output y;

    integer i, j;
    reg [31:0] lut;

    initial begin
        for (i = 0; i &lt; 32; i = i+1) begin
            lut[i] = i &gt; 1;
            for (j = 2; j*j &lt;= i; j = j+1)
                if (i <span class="c">% j == 0)</span>
                    lut[i] = 0;
        end
    end

    assign y = lut[a];
endmodule
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> 2/3<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>8pt<span class="nb">}{</span>10pt<span class="nb">}</span><span class="k">\selectfont</span>, language=Verilog]
module carryadd(a, b, y);
    parameter WIDTH = 8;
    input [WIDTH-1:0] a, b;
    output [WIDTH-1:0] y;

    genvar i;
    generate
        for (i = 0; i &lt; WIDTH; i = i+1) begin:STAGE
            wire IN1 = a[i], IN2 = b[i];
            wire C, Y;
            if (i == 0)
                assign C = IN1 <span class="nb">&amp;</span> IN2, Y = IN1 <span class="nb">^</span> IN2;
            else
                assign C = (IN1 <span class="nb">&amp;</span> IN2) | ((IN1 | IN2) <span class="nb">&amp;</span> STAGE[i-1].C),
                       Y = IN1 <span class="nb">^</span> IN2 <span class="nb">^</span> STAGE[i-1].C;
            assign y[i] = Y;
        end
    endgenerate
endmodule
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}</span>[fragile]<span class="nb">{</span><span class="k">\subsecname</span><span class="nb">{}</span> 3/3<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>lstlisting<span class="nb">}</span>[xleftmargin=1cm, basicstyle=<span class="k">\ttfamily\fontsize</span><span class="nb">{</span>7pt<span class="nb">}{</span>8.5pt<span class="nb">}</span><span class="k">\selectfont</span>, language=Verilog]
module cam(clk, wr<span class="nb">_</span>enable, wr<span class="nb">_</span>addr, wr<span class="nb">_</span>data, rd<span class="nb">_</span>data, rd<span class="nb">_</span>addr, rd<span class="nb">_</span>match);
    parameter WIDTH = 8;
    parameter DEPTH = 16;
    localparam ADDR<span class="nb">_</span>BITS = <span class="s">$</span><span class="nb">clog</span><span class="m">2</span><span class="o">(</span><span class="nb">DEPTH</span><span class="o">-</span><span class="m">1</span><span class="o">)</span><span class="nb">;</span>

<span class="nb">    input clk, wr_enable;</span>
<span class="nb">    input </span><span class="o">[</span><span class="nb">ADDR_BITS</span><span class="o">-</span><span class="m">1</span><span class="nb">:</span><span class="m">0</span><span class="o">]</span><span class="nb"> wr_addr;</span>
<span class="nb">    input </span><span class="o">[</span><span class="nb">WIDTH</span><span class="o">-</span><span class="m">1</span><span class="nb">:</span><span class="m">0</span><span class="o">]</span><span class="nb"> wr_data, rd_data;</span>
<span class="nb">    output reg </span><span class="o">[</span><span class="nb">ADDR_BITS</span><span class="o">-</span><span class="m">1</span><span class="nb">:</span><span class="m">0</span><span class="o">]</span><span class="nb"> rd_addr;</span>
<span class="nb">    output reg rd_match;</span>

<span class="nb">    integer i;</span>
<span class="nb">    reg </span><span class="o">[</span><span class="nb">WIDTH</span><span class="o">-</span><span class="m">1</span><span class="nb">:</span><span class="m">0</span><span class="o">]</span><span class="nb"> mem </span><span class="o">[</span><span class="m">0</span><span class="nb">:DEPTH</span><span class="o">-</span><span class="m">1</span><span class="o">]</span><span class="nb">;</span>

<span class="nb">    always @</span><span class="o">(</span><span class="nb">posedge clk</span><span class="o">)</span><span class="nb"> begin</span>
<span class="nb">        rd_addr &lt;</span><span class="o">=</span><span class="nb"> &#39;bx;</span>
<span class="nb">        rd_match &lt;</span><span class="o">=</span><span class="nb"> </span><span class="m">0</span><span class="nb">;</span>
<span class="nb">        for </span><span class="o">(</span><span class="nb">i </span><span class="o">=</span><span class="nb"> </span><span class="m">0</span><span class="nb">; i &lt; DEPTH; i </span><span class="o">=</span><span class="nb"> i</span><span class="o">+</span><span class="m">1</span><span class="o">)</span><span class="nb"></span>
<span class="nb">            if </span><span class="o">(</span><span class="nb">mem</span><span class="o">[</span><span class="nb">i</span><span class="o">]</span><span class="nb"> </span><span class="o">==</span><span class="nb"> rd_data</span><span class="o">)</span><span class="nb"> begin</span>
<span class="nb">                rd_addr &lt;</span><span class="o">=</span><span class="nb"> i;</span>
<span class="nb">                rd_match &lt;</span><span class="o">=</span><span class="nb"> </span><span class="m">1</span><span class="nb">;</span>
<span class="nb">            end</span>
<span class="nb">        if </span><span class="o">(</span><span class="nb">wr_enable</span><span class="o">)</span><span class="nb"></span>
<span class="nb">            mem</span><span class="o">[</span><span class="nb">wr_addr</span><span class="o">]</span><span class="nb"> &lt;</span><span class="o">=</span><span class="nb"> wr_data;</span>
<span class="nb">    end</span>
<span class="nb">endmodule</span>
<span class="nv">\end</span><span class="nb">{lstlisting}</span>
<span class="nv">\end</span><span class="nb">{frame}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="nv">\subsection</span><span class="nb">{Currently unsupported Verilog</span><span class="o">-</span><span class="m">2005</span><span class="nb"> language features}</span>

<span class="nv">\begin</span><span class="nb">{frame}{</span><span class="nv">\subsecname</span><span class="nb">}</span>
<span class="nv">\begin</span><span class="nb">{itemize}</span>
<span class="nv">\item</span><span class="nb"> Tri</span><span class="o">-</span><span class="nb">state logic</span>
<span class="nv">\item</span><span class="nb"> The wor</span><span class="o">/</span><span class="nb">wand wire types </span><span class="o">(</span><span class="nb">maybe for </span><span class="m">0</span><span class="nb">.</span><span class="m">5</span><span class="o">)</span><span class="nb"></span>
<span class="nv">\item</span><span class="nb"> Latched logic </span><span class="o">(</span><span class="nb">is synthesized as logic with feedback loops</span><span class="o">)</span><span class="nb"></span>
<span class="nv">\item</span><span class="nb"> Some non</span><span class="o">-</span><span class="nb">synthesizable features that should be ignored in synthesis are not supported by the parser and cause a parser error </span><span class="o">(</span><span class="nb">file a bug report if you encounter this problem</span><span class="o">)</span><span class="nb"></span>
<span class="nv">\end</span><span class="nb">{itemize}</span>
<span class="nv">\end</span><span class="nb">{frame}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="nv">\subsection</span><span class="nb">{Verification of Yosys}</span>

<span class="nv">\begin</span><span class="nb">{frame}{</span><span class="nv">\subsecname</span><span class="nb">}</span>
<span class="nb">Continuously checking the correctness of Yosys and making sure that new features</span>
<span class="nb">do not break old ones is a high priority in Yosys.</span>

<span class="nv">\bigskip</span><span class="nb"></span>
<span class="nb">Two external test suites have been built for Yosys: VlogHammer and yosys</span><span class="o">-</span><span class="nb">bigsim</span>
<span class="o">(</span><span class="nb">see next slides</span><span class="o">)</span><span class="nb"></span>

<span class="nv">\bigskip</span><span class="nb"></span>
<span class="nb">In addition to that, yosys comes with </span><span class="s">$</span><span class="k">\approx\!</span>200<span class="s">$</span><span class="nb"> test cases used in ``{</span><span class="nv">\tt</span><span class="nb"> make test}&#39;&#39;.</span>

<span class="nv">\bigskip</span><span class="nb"></span>
<span class="nb">A debug build of Yosys also contains a lot of asserts and checks the integrity of</span>
<span class="nb">the internal state after each command.</span>
<span class="nv">\end</span><span class="nb">{frame}</span>

<span class="nv">\begin</span><span class="nb">{frame}</span><span class="o">[</span><span class="nb">fragile</span><span class="o">]</span><span class="nb">{</span><span class="nv">\subsecname</span><span class="nb">{} </span><span class="o">--</span><span class="nb"> VlogHammer}</span>
<span class="nb">VlogHammer is a Verilog regression test suite developed to test the different</span>
<span class="nb">subsystems in Yosys by comparing them to each other and to the output created</span>
<span class="nb">by some other tools </span><span class="o">(</span><span class="nb">Xilinx Vivado, Xilinx XST, Altera Quartus II, ...</span><span class="o">)</span><span class="nb">.</span>

<span class="nv">\bigskip</span><span class="nb"></span>
<span class="nb">Yosys Subsystems tested: Verilog frontend, const folding, const eval, technology mapping,</span>
<span class="nb">simulation models, SAT models.</span>

<span class="nv">\bigskip</span><span class="nb"></span>
<span class="nb">Thousands of auto</span><span class="o">-</span><span class="nb">generated test cases containing code such as:</span>
<span class="nv">\begin</span><span class="nb">{lstlisting}</span><span class="o">[</span><span class="nb">xleftmargin</span><span class="o">=</span><span class="m">1</span><span class="nb">cm, basicstyle</span><span class="o">=</span><span class="nv">\ttfamily\fontsize</span><span class="nb">{</span><span class="m">8</span><span class="nb">pt}{</span><span class="m">10</span><span class="nb">pt}</span><span class="nv">\selectfont</span><span class="nb">, language</span><span class="o">=</span><span class="nb">Verilog</span><span class="o">]</span><span class="nb"></span>
<span class="nb">assign y</span><span class="m">9</span><span class="nb"> </span><span class="o">=</span><span class="nb"> </span><span class="s">$</span>signed(((+<span class="s">$</span><span class="nb">signed</span><span class="o">((</span><span class="nb">^</span><span class="o">(</span><span class="m">6</span><span class="nb">&#39;d</span><span class="m">2</span><span class="nb"> </span><span class="o">**</span><span class="nb"> a</span><span class="m">2</span><span class="o">))))</span><span class="nb">&lt;</span><span class="s">$</span>unsigned(<span class="s">$</span><span class="nb">unsigned</span><span class="o">(((+</span><span class="nb">a</span><span class="m">3</span><span class="o">))))))</span><span class="nb">;</span>
<span class="nb">assign y</span><span class="m">10</span><span class="nb"> </span><span class="o">=</span><span class="nb"> </span><span class="o">(-((+((+</span><span class="nb">{</span><span class="m">2</span><span class="nb">{</span><span class="o">(</span><span class="nb">~^p</span><span class="m">13</span><span class="o">)</span><span class="nb">}}</span><span class="o">)))</span><span class="nb">^~</span><span class="o">(!</span><span class="nb">{{b</span><span class="m">5</span><span class="nb">,b</span><span class="m">1</span><span class="nb">,a</span><span class="m">0</span><span class="nb">},</span><span class="o">(</span><span class="nb">a</span><span class="m">1</span><span class="nb">&amp;p</span><span class="m">12</span><span class="o">)</span><span class="nb">,</span><span class="o">(</span><span class="nb">a</span><span class="m">4</span><span class="o">+</span><span class="nb">a</span><span class="m">3</span><span class="o">)</span><span class="nb">}</span><span class="o">)))</span><span class="nb">;</span>
<span class="nb">assign y</span><span class="m">11</span><span class="nb"> </span><span class="o">=</span><span class="nb"> </span><span class="o">(</span><span class="nb">~&amp;</span><span class="o">(-</span><span class="nb">{</span><span class="o">(-</span><span class="m">3</span><span class="nb">&#39;sd</span><span class="m">3</span><span class="o">)</span><span class="nb">,</span><span class="o">(</span><span class="s">$</span>unsigned(<span class="s">$</span><span class="nb">signed</span><span class="o">(</span><span class="s">$</span>unsigned(<span class="nb">{</span>p0,b4,b1<span class="nb">}</span>))))<span class="nb">}</span>));
<span class="k">\end</span><span class="nb">{</span>lstlisting<span class="nb">}</span>

<span class="k">\bigskip</span>
Some bugs in Yosys where found and fixed thanks to VlogHammer. Over 50 bugs in
the other tools used as external reference where found and reported so far.
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- yosys-bigsim<span class="nb">}</span>
yosys-bigsim is a collection of real-world open-source Verilog designs and test
benches. yosys-bigsim compares the testbench outputs of simulations of the original
Verilog code and synthesis results.

<span class="k">\bigskip</span>
The following designs are included in yosys-bigsim (excerpt):
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> <span class="nb">{</span><span class="k">\tt</span> openmsp430<span class="nb">}</span> -- an MSP430 compatible 16 bit CPU
<span class="k">\item</span> <span class="nb">{</span><span class="k">\tt</span> aes<span class="k">\_</span>5cycle<span class="k">\_</span>2stage<span class="nb">}</span> -- an AES encryption core
<span class="k">\item</span> <span class="nb">{</span><span class="k">\tt</span> softusb<span class="k">\_</span>navre<span class="nb">}</span> -- an AVR compatible 8 bit CPU
<span class="k">\item</span> <span class="nb">{</span><span class="k">\tt</span> amber23<span class="nb">}</span> -- an ARMv2 compatible 32 bit CPU
<span class="k">\item</span> <span class="nb">{</span><span class="k">\tt</span> lm32<span class="nb">}</span> -- another 32 bit CPU from Lattice Semiconductor
<span class="k">\item</span> <span class="nb">{</span><span class="k">\tt</span> verilog-pong<span class="nb">}</span> -- a hardware pong game with VGA output
<span class="k">\item</span> <span class="nb">{</span><span class="k">\tt</span> elliptic<span class="k">\_</span>curve<span class="k">\_</span>group<span class="nb">}</span> -- ECG point-add and point-scalar-mul core
<span class="k">\item</span> <span class="nb">{</span><span class="k">\tt</span> reed<span class="k">\_</span>solomon<span class="k">\_</span>decoder<span class="nb">}</span> -- a Reed-Solomon Error Correction Decoder
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Benefits of Open Source HDL Synthesis<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Cost (also applies to ``free as in free beer&#39;&#39; solutions)
<span class="k">\item</span> Availability and Reproducibility
<span class="k">\item</span> Framework- and all-in-one-aspects
<span class="k">\item</span> Educational Tool
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

<span class="k">\bigskip</span>

Yosys is open source under the ISC license.
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- 1/3<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Cost (also applies to ``free as in free beer&#39;&#39; solutions): <span class="k">\smallskip\par</span>
Today the cost for a mask set in <span class="s">$</span><span class="nv">\unit</span><span class="o">[</span><span class="m">180</span><span class="o">]</span><span class="nb">{nm}</span><span class="s">$</span> technology is far less than
the cost for the design tools needed to design the mask layouts. Open Source
ASIC flows are an important enabler for ASIC-level Open Source Hardware.

<span class="k">\bigskip</span>
<span class="k">\item</span> Availability and Reproducibility: <span class="k">\smallskip\par</span>
If you are a researcher who is publishing, you want to use tools that everyone
else can also use. Even if most universities have access to all major
commercial tools, you usually do not have easy access to the version that was
used in a research project a couple of years ago. With Open Source tools you
can even release the source code of the tool you have used alongside your data.
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- 2/3<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Framework: <span class="k">\smallskip\par</span>
Yosys is not only a tool. It is a framework that can be used as basis for other
developments, so researchers and hackers alike do not need to re-invent the
basic functionality. Extensibility was one of Yosys&#39; design goals.

<span class="k">\bigskip</span>
<span class="k">\item</span> All-in-one: <span class="k">\smallskip\par</span>
Because of the framework characteristics of Yosys, an increasing number of features
become available in one tool. Yosys not only can be used for circuit synthesis but
also for formal equivalence checking, SAT solving, and for circuit analysis, to
name just a few other application domains. With proprietary software one needs to
learn a new tool for each of these applications.
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- 3/3<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Educational Tool: <span class="k">\smallskip\par</span>
Proprietary synthesis tools are at times very secretive about their inner
workings. They often are ``black boxes&#39;&#39;. Yosys is very open about its
internals and it is easy to observe the different steps of synthesis.
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\begin</span><span class="nb">{</span>block<span class="nb">}{</span>Yosys is licensed under the ISC license:<span class="nb">}</span>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
<span class="k">\end</span><span class="nb">{</span>block<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Typical Applications for Yosys<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Synthesis of final production designs
<span class="k">\item</span> Pre-production synthesis (trial runs before investing in other tools)
<span class="k">\item</span> Conversion of full-featured Verilog to simple Verilog
<span class="k">\item</span> Conversion of Verilog to other formats (BLIF, BTOR, etc)
<span class="k">\item</span> Demonstrating synthesis algorithms (e.g. for educational purposes)
<span class="k">\item</span> Framework for experimenting with new algorithms
<span class="k">\item</span> Framework for building custom flows<span class="k">\footnote</span><span class="na">[frame]</span><span class="nb">{</span>Not limited to synthesis
but also formal verification, reverse engineering, ...<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Projects (that I know of) using Yosys<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- (1/2)<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Ongoing PhD project on coarse grain synthesis <span class="k">\\</span>
<span class="nb">{</span><span class="k">\setlength</span><span class="nb">{</span><span class="k">\parindent</span><span class="nb">}{</span>0.5cm<span class="nb">}</span><span class="k">\footnotesize</span>
Johann Glaser and C. Wolf. Methodology and Example-Driven Interconnect
Synthesis for Designing Heterogeneous Coarse-Grain Reconfigurable
Architectures. In Jan Haase, editor, <span class="k">\it</span> Models, Methods, and Tools for Complex
Chip Design. Lecture Notes in Electrical Engineering. Volume 265, 2014, pp
201-221. Springer, 2013.<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\item</span> I know several people that use Yosys simply as Verilog frontend for other
flows (using either the BLIF and BTOR backends).

<span class="k">\bigskip</span>
<span class="k">\item</span> I know some analog chip designers that use Yosys for small digital
control logic because it is simpler than setting up a commercial flow.
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">{}</span> -- (2/2)<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Efabless
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\smallskip</span> <span class="k">\item</span> Not much information on the website (<span class="k">\url</span><span class="nb">{</span>http://efabless.com<span class="nb">}</span>) yet.
<span class="k">\smallskip</span> <span class="k">\item</span> Very cheap 180nm prototyping process (partnering with various fabs)
<span class="k">\smallskip</span> <span class="k">\item</span> A semiconductor company, NOT an EDA company
<span class="k">\smallskip</span> <span class="k">\item</span> Web-based design environment
<span class="k">\smallskip</span> <span class="k">\item</span> HDL Synthesis using Yosys
<span class="k">\smallskip</span> <span class="k">\item</span> Custom place<span class="k">\&amp;</span>route tool

<span class="k">\bigskip</span>
<span class="k">\item</span> efabless is building an Open Source IC as reference design. <span class="k">\\</span>
<span class="k">\hskip</span>1cm (to be announced soon: <span class="k">\url</span><span class="nb">{</span>http://www.openic.io<span class="nb">}</span>)
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Supported Platforms<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Main development OS: Kubuntu 14.04
<span class="k">\item</span> There is a PPA for ubuntu (not maintained by me)
<span class="k">\item</span> Any current Debian-based system should work out of the box
<span class="k">\item</span> When building on other Linux distributions:
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Needs compiler with some C++11 support
<span class="k">\item</span> See README file for build instructions
<span class="k">\item</span> Post to the subreddit if you get stuck
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Ported to OS X (Darwin) and OpenBSD
<span class="k">\item</span> Native win32 build with VisualStudio
<span class="k">\item</span> Cross win32 build with MXE
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Other Open Source Tools<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Icarus Verilog <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="nb">{}</span>Verilog Simulation (and also a good syntax checker) <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="nb">{}</span><span class="k">\url</span><span class="nb">{</span>http://iverilog.icarus.com/<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\item</span> Qflow (incl. TimberWolf, qrouter and Magic) <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="nb">{}</span>A complete ASIC synthesis flow, using Yosys and ABC <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="nb">{}</span><span class="k">\url</span><span class="nb">{</span>http://opencircuitdesign.com/qflow/<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\item</span> ABC <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="nb">{}</span>Logic optimization, technology mapping, and more <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="nb">{}</span><span class="k">\url</span><span class="nb">{</span>http://www.eecs.berkeley.edu/~alanmi/abc/<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Yosys needs you<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\dots</span> as an active user:
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Use Yosys for on your own projects
<span class="k">\item</span> .. even if you are not using it as final synthesis tool
<span class="k">\item</span> Join the discussion on the Subreddit
<span class="k">\item</span> Report bugs and send in feature requests
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\dots</span> as a developer:
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Use Yosys as environment for your (research) work
<span class="k">\item</span> .. you might also want to look into ABC for logic-level stuff
<span class="k">\item</span> Fork the project on github or create loadable plugins
<span class="k">\item</span> We need a VHDL frontend or a good VHDL-to-Verilog converter
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Documentation, Downloads, Contacts<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Website: <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="k">\url</span><span class="nb">{</span>https://yosyshq.net/yosys/<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\item</span> Manual, Command Reference, Application Notes: <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="k">\url</span><span class="nb">{</span>https://yosyshq.net/yosys/documentation.html<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\item</span> Instead of a mailing list we have a SubReddit: <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="k">\url</span><span class="nb">{</span>http://www.reddit.com/r/yosys/<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\item</span> Direct link to the source code: <span class="k">\\</span>
<span class="k">\smallskip\hskip</span>1cm<span class="k">\url</span><span class="nb">{</span>https://github.com/YosysHQ/yosys<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>

<span class="c">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>

<span class="k">\subsection</span><span class="nb">{</span>Summary<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>frame<span class="nb">}{</span><span class="k">\subsecname</span><span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
<span class="k">\item</span> Yosys is a powerful tool and framework for Verilog synthesis.
<span class="k">\item</span> It uses a command-based interface and can be controlled by scripts.
<span class="k">\item</span> By combining existing commands and implementing new commands Yosys can
be used in a wide range of application far beyond simple synthesis.
<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\bigskip</span>
<span class="k">\begin</span><span class="nb">{</span>center<span class="nb">}</span>
Questions?
<span class="k">\end</span><span class="nb">{</span>center<span class="nb">}</span>

<span class="k">\bigskip</span>
<span class="k">\bigskip</span>
<span class="k">\begin</span><span class="nb">{</span>center<span class="nb">}</span>
<span class="k">\url</span><span class="nb">{</span>https://yosyshq.net/yosys/<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>center<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>frame<span class="nb">}</span>
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2025-09-11 16:01:09 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
olding me clears the\nthe keyboard capture flag");
            if (ImGui::IsItemActive())
                ImGui::CaptureKeyboardFromApp(false);

            ImGui::TreePop();
        }

        if (ImGui::TreeNode("Tabbing"))
        {
            ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
            static char buf[32] = "dummy";
            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
            ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
            ImGui::PushAllowKeyboardFocus(false);
            ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
            //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
            ImGui::PopAllowKeyboardFocus();
            ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
            ImGui::TreePop();
        }

        if (ImGui::TreeNode("Focus from code"))
        {
            bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
            bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
            bool focus_3 = ImGui::Button("Focus on 3");
            int has_focus = 0;
            static char buf[128] = "click on a button to set focus";

            if (focus_1) ImGui::SetKeyboardFocusHere();
            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
            if (ImGui::IsItemActive()) has_focus = 1;

            if (focus_2) ImGui::SetKeyboardFocusHere();
            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
            if (ImGui::IsItemActive()) has_focus = 2;

            ImGui::PushAllowKeyboardFocus(false);
            if (focus_3) ImGui::SetKeyboardFocusHere();
            ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
            if (ImGui::IsItemActive()) has_focus = 3;
            ImGui::PopAllowKeyboardFocus();

            if (has_focus)
                ImGui::Text("Item with focus: %d", has_focus);
            else
                ImGui::Text("Item with focus: <none>");

            // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
            static float f3[3] = { 0.0f, 0.0f, 0.0f };
            int focus_ahead = -1;
            if (ImGui::Button("Focus on X")) focus_ahead = 0; ImGui::SameLine();
            if (ImGui::Button("Focus on Y")) focus_ahead = 1; ImGui::SameLine();
            if (ImGui::Button("Focus on Z")) focus_ahead = 2;
            if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
            ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);

            ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
            ImGui::TreePop();
        }

        if (ImGui::TreeNode("Dragging"))
        {
            ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
            for (int button = 0; button < 3; button++)
                ImGui::Text("IsMouseDragging(%d):\n  w/ default threshold: %d,\n  w/ zero threshold: %d\n  w/ large threshold: %d",
                    button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f));
            ImGui::Button("Drag Me");
            if (ImGui::IsItemActive())
            {
                // Draw a line between the button and the mouse cursor
                ImDrawList* draw_list = ImGui::GetWindowDrawList();
                draw_list->PushClipRectFullScreen();
                draw_list->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f);
                draw_list->PopClipRect();

                // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold)
                // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta()
                ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
                ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
                ImVec2 mouse_delta = io.MouseDelta;
                ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y);
            }
            ImGui::TreePop();
        }

        if (ImGui::TreeNode("Mouse cursors"))
        {
            const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand" };
            IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);

            ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
            ImGui::Text("Hover to see mouse cursors:");
            ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.");
            for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
            {
                char label[32];
                sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
                ImGui::Bullet(); ImGui::Selectable(label, false);
                if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
                    ImGui::SetMouseCursor(i);
            }
            ImGui::TreePop();
        }
    }

    // End of ShowDemoWindow()
    ImGui::End();
}

//-----------------------------------------------------------------------------
// [SECTION] Style Editor / ShowStyleEditor()
//-----------------------------------------------------------------------------

// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
// Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally.
bool ImGui::ShowStyleSelector(const char* label)
{
    static int style_idx = -1;
    if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
    {
        switch (style_idx)
        {
        case 0: ImGui::StyleColorsClassic(); break;
        case 1: ImGui::StyleColorsDark(); break;
        case 2: ImGui::StyleColorsLight(); break;
        }
        return true;
    }
    return false;
}

// Demo helper function to select among loaded fonts.
// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
void ImGui::ShowFontSelector(const char* label)
{
    ImGuiIO& io = ImGui::GetIO();
    ImFont* font_current = ImGui::GetFont();
    if (ImGui::BeginCombo(label, font_current->GetDebugName()))
    {
        for (int n = 0; n < io.Fonts->Fonts.Size; n++)
            if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current))
                io.FontDefault = io.Fonts->Fonts[n];
        ImGui::EndCombo();
    }
    ImGui::SameLine();
    ShowHelpMarker(
        "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
        "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
        "- Read FAQ and documentation in misc/fonts/ for more details.\n"
        "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
}

void ImGui::ShowStyleEditor(ImGuiStyle* ref)
{
    // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
    ImGuiStyle& style = ImGui::GetStyle();
    static ImGuiStyle ref_saved_style;

    // Default to using internal storage as reference
    static bool init = true;
    if (init && ref == NULL)
        ref_saved_style = style;
    init = false;
    if (ref == NULL)
        ref = &ref_saved_style;

    ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);

    if (ImGui::ShowStyleSelector("Colors##Selector"))
        ref_saved_style = style;
    ImGui::ShowFontSelector("Fonts##Selector");

    // Simplified Settings
    if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
        style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
    { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; }
    ImGui::SameLine();
    { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
    ImGui::SameLine();
    { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }

    // Save/Revert button
    if (ImGui::Button("Save Ref"))
        *ref = ref_saved_style = style;
    ImGui::SameLine();
    if (ImGui::Button("Revert Ref"))
        style = *ref;
    ImGui::SameLine();
    ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");

    if (ImGui::TreeNode("Rendering"))
    {
        ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
        ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
        ImGui::PushItemWidth(100);
        ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, "%.2f", 2.0f);
        if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
        ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
        ImGui::PopItemWidth();
        ImGui::TreePop();
    }

    if (ImGui::TreeNode("Settings"))
    {
        ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
        ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f");
        ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
        ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
        ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
        ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
        ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
        ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
        ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
        ImGui::Text("BorderSize");
        ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
        ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
        ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
        ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
        ImGui::Text("Rounding");
        ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f");
        ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f");
        ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
        ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
        ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
        ImGui::Text("Alignment");
        ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
        ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content.");
        ImGui::Text("Safe Area Padding"); ImGui::SameLine(); ShowHelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
        ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
        ImGui::TreePop();
    }

    if (ImGui::TreeNode("Colors"))
    {
        static int output_dest = 0;
        static bool output_only_modified = true;
        if (ImGui::Button("Export Unsaved"))
        {
            if (output_dest == 0)
                ImGui::LogToClipboard();
            else
                ImGui::LogToTTY();
            ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
            for (int i = 0; i < ImGuiCol_COUNT; i++)
            {
                const ImVec4& col = style.Colors[i];
                const char* name = ImGui::GetStyleColorName(i);
                if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
                    ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 23-(int)strlen(name), "", col.x, col.y, col.z, col.w);
            }
            ImGui::LogFinish();
        }
        ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
        ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);

        ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu.");

        static ImGuiTextFilter filter;
        filter.Draw("Filter colors", 200);

        static ImGuiColorEditFlags alpha_flags = 0;
        ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine();
        ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine();
        ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf);

        ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
        ImGui::PushItemWidth(-160);
        for (int i = 0; i < ImGuiCol_COUNT; i++)
        {
            const char* name = ImGui::GetStyleColorName(i);
            if (!filter.PassFilter(name))
                continue;
            ImGui::PushID(i);
            ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
            if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
            {
                // Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons.
                // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient!
                ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
                ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
            }
            ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
            ImGui::TextUnformatted(name);
            ImGui::PopID();
        }
        ImGui::PopItemWidth();
        ImGui::EndChild();

        ImGui::TreePop();
    }

    bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size);
    if (fonts_opened)
    {
        ImFontAtlas* atlas = ImGui::GetIO().Fonts;
        if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
        {
            ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
            ImGui::TreePop();
        }
        ImGui::PushItemWidth(100);
        for (int i = 0; i < atlas->Fonts.Size; i++)
        {
            ImFont* font = atlas->Fonts[i];
            ImGui::PushID(font);
            bool font_details_opened = ImGui::TreeNode(font, "Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
            ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font;
            if (font_details_opened)
            {
                ImGui::PushFont(font);
                ImGui::Text("The quick brown fox jumps over the lazy dog");
                ImGui::PopFont();
                ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");   // Scale only this font
                ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
                ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f");
                ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
                ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
                ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));
                for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
                    if (ImFontConfig* cfg = &font->ConfigData[config_i])
                        ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
                if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
                {
                    // Display all glyphs of the fonts in separate pages of 256 characters
                    for (int base = 0; base < 0x10000; base += 256)
                    {
                        int count = 0;
                        for (int n = 0; n < 256; n++)
                            count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0;
                        if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph"))
                        {
                            float cell_size = font->FontSize * 1;
                            float cell_spacing = style.ItemSpacing.y;
                            ImVec2 base_pos = ImGui::GetCursorScreenPos();
                            ImDrawList* draw_list = ImGui::GetWindowDrawList();
                            for (int n = 0; n < 256; n++)
                            {
                                ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
                                ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
                                const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base+n));
                                draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50));
                                if (glyph)
                                    font->RenderChar(draw_list, cell_size, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string.
                                if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
                                {
                                    ImGui::BeginTooltip();
                                    ImGui::Text("Codepoint: U+%04X", base+n);
                                    ImGui::Separator();
                                    ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
                                    ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
                                    ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
                                    ImGui::EndTooltip();
                                }
                            }
                            ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
                            ImGui::TreePop();
                        }
                    }
                    ImGui::TreePop();
                }
                ImGui::TreePop();
            }
            ImGui::PopID();
        }
        static float window_scale = 1.0f;
        ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f");              // scale only this window
        ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything
        ImGui::PopItemWidth();
        ImGui::SetWindowFontScale(window_scale);
        ImGui::TreePop();
    }

    ImGui::PopItemWidth();
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
//-----------------------------------------------------------------------------

// Demonstrate creating a fullscreen menu bar and populating it.
static void ShowExampleAppMainMenuBar()
{
    if (ImGui::BeginMainMenuBar())
    {
        if (ImGui::BeginMenu("File"))
        {
            ShowExampleMenuFile();
            ImGui::EndMenu();
        }
        if (ImGui::BeginMenu("Edit"))
        {
            if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
            if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
            ImGui::Separator();
            if (ImGui::MenuItem("Cut", "CTRL+X")) {}
            if (ImGui::MenuItem("Copy", "CTRL+C")) {}
            if (ImGui::MenuItem("Paste", "CTRL+V")) {}
            ImGui::EndMenu();
        }
        ImGui::EndMainMenuBar();
    }
}

static void ShowExampleMenuFile()
{
    ImGui::MenuItem("(dummy menu)", NULL, false, false);
    if (ImGui::MenuItem("New")) {}
    if (ImGui::MenuItem("Open", "Ctrl+O")) {}
    if (ImGui::BeginMenu("Open Recent"))
    {
        ImGui::MenuItem("fish_hat.c");
        ImGui::MenuItem("fish_hat.inl");
        ImGui::MenuItem("fish_hat.h");
        if (ImGui::BeginMenu("More.."))
        {
            ImGui::MenuItem("Hello");
            ImGui::MenuItem("Sailor");
            if (ImGui::BeginMenu("Recurse.."))
            {
                ShowExampleMenuFile();
                ImGui::EndMenu();
            }
            ImGui::EndMenu();
        }
        ImGui::EndMenu();
    }
    if (ImGui::MenuItem("Save", "Ctrl+S")) {}
    if (ImGui::MenuItem("Save As..")) {}
    ImGui::Separator();
    if (ImGui::BeginMenu("Options"))
    {
        static bool enabled = true;
        ImGui::MenuItem("Enabled", "", &enabled);
        ImGui::BeginChild("child", ImVec2(0, 60), true);
        for (int i = 0; i < 10; i++)
            ImGui::Text("Scrolling Text %d", i);
        ImGui::EndChild();
        static float f = 0.5f;
        static int n = 0;
        static bool b = true;
        ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
        ImGui::InputFloat("Input", &f, 0.1f);
        ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
        ImGui::Checkbox("Check", &b);
        ImGui::EndMenu();
    }
    if (ImGui::BeginMenu("Colors"))
    {
        float sz = ImGui::GetTextLineHeight();
        for (int i = 0; i < ImGuiCol_COUNT; i++)
        {
            const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
            ImVec2 p = ImGui::GetCursorScreenPos();
            ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x+sz, p.y+sz), ImGui::GetColorU32((ImGuiCol)i));
            ImGui::Dummy(ImVec2(sz, sz));
            ImGui::SameLine();
            ImGui::MenuItem(name);
        }
        ImGui::EndMenu();
    }
    if (ImGui::BeginMenu("Disabled", false)) // Disabled
    {
        IM_ASSERT(0);
    }
    if (ImGui::MenuItem("Checked", NULL, true)) {}
    if (ImGui::MenuItem("Quit", "Alt+F4")) {}
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
//-----------------------------------------------------------------------------

// Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
// For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
struct ExampleAppConsole
{
    char                  InputBuf[256];
    ImVector<char*>       Items;
    bool                  ScrollToBottom;
    ImVector<char*>       History;
    int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
    ImVector<const char*> Commands;

    ExampleAppConsole()
    {
        ClearLog();
        memset(InputBuf, 0, sizeof(InputBuf));
        HistoryPos = -1;
        Commands.push_back("HELP");
        Commands.push_back("HISTORY");
        Commands.push_back("CLEAR");
        Commands.push_back("CLASSIFY");  // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
        AddLog("Welcome to Dear ImGui!");
    }
    ~ExampleAppConsole()
    {
        ClearLog();
        for (int i = 0; i < History.Size; i++)
            free(History[i]);
    }

    // Portable helpers
    static int   Stricmp(const char* str1, const char* str2)         { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
    static int   Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; }
    static char* Strdup(const char *str)                             { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); }
    static void  Strtrim(char* str)                                  { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; }

    void    ClearLog()
    {
        for (int i = 0; i < Items.Size; i++)
            free(Items[i]);
        Items.clear();
        ScrollToBottom = true;
    }

    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
    {
        // FIXME-OPT
        char buf[1024];
        va_list args;
        va_start(args, fmt);
        vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
        buf[IM_ARRAYSIZE(buf)-1] = 0;
        va_end(args);
        Items.push_back(Strdup(buf));
        ScrollToBottom = true;
    }

    void    Draw(const char* title, bool* p_open)
    {
        ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
        if (!ImGui::Begin(title, p_open))
        {
            ImGui::End();
            return;
        }

        // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
        // Here we create a context menu only available from the title bar.
        if (ImGui::BeginPopupContextItem())
        {
            if (ImGui::MenuItem("Close Console"))
                *p_open = false;
            ImGui::EndPopup();
        }

        ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
        ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");

        // TODO: display items starting from the bottom

        if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
        if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
        if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
        bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine();
        if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
        //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }

        ImGui::Separator();

        ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
        static ImGuiTextFilter filter;
        filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
        ImGui::PopStyleVar();
        ImGui::Separator();

        const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
        ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText
        if (ImGui::BeginPopupContextWindow())
        {
            if (ImGui::Selectable("Clear")) ClearLog();
            ImGui::EndPopup();
        }

        // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
        // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
        // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements.
        // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
        //     ImGuiListClipper clipper(Items.Size);
        //     while (clipper.Step())
        //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
        // However, note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list.
        // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter,
        // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code!
        // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list.
        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
        if (copy_to_clipboard)
            ImGui::LogToClipboard();
        ImVec4 col_default_text = ImGui::GetStyleColorVec4(ImGuiCol_Text);
        for (int i = 0; i < Items.Size; i++)
        {
            const char* item = Items[i];
            if (!filter.PassFilter(item))
                continue;
            ImVec4 col = col_default_text;
            if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f);
            else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f);
            ImGui::PushStyleColor(ImGuiCol_Text, col);
            ImGui::TextUnformatted(item);
            ImGui::PopStyleColor();
        }
        if (copy_to_clipboard)
            ImGui::LogFinish();
        if (ScrollToBottom)
            ImGui::SetScrollHereY(1.0f);
        ScrollToBottom = false;
        ImGui::PopStyleVar();
        ImGui::EndChild();
        ImGui::Separator();

        // Command-line
        bool reclaim_focus = false;
        if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
        {
            char* s = InputBuf;
            Strtrim(s);
            if (s[0])
                ExecCommand(s);
            strcpy(s, "");
            reclaim_focus = true;
        }

        // Auto-focus on window apparition
        ImGui::SetItemDefaultFocus();
        if (reclaim_focus)
            ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget

        ImGui::End();
    }

    void    ExecCommand(const char* command_line)
    {
        AddLog("# %s\n", command_line);

        // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal.
        HistoryPos = -1;
        for (int i = History.Size-1; i >= 0; i--)
            if (Stricmp(History[i], command_line) == 0)
            {
                free(History[i]);
                History.erase(History.begin() + i);
                break;
            }
        History.push_back(Strdup(command_line));

        // Process command
        if (Stricmp(command_line, "CLEAR") == 0)
        {
            ClearLog();
        }
        else if (Stricmp(command_line, "HELP") == 0)
        {
            AddLog("Commands:");
            for (int i = 0; i < Commands.Size; i++)
                AddLog("- %s", Commands[i]);
        }
        else if (Stricmp(command_line, "HISTORY") == 0)
        {
            int first = History.Size - 10;
            for (int i = first > 0 ? first : 0; i < History.Size; i++)
                AddLog("%3d: %s\n", i, History[i]);
        }
        else
        {
            AddLog("Unknown command: '%s'\n", command_line);
        }
    }

    static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
    {
        ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
        return console->TextEditCallback(data);
    }

    int     TextEditCallback(ImGuiInputTextCallbackData* data)
    {
        //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
        switch (data->EventFlag)
        {
        case ImGuiInputTextFlags_CallbackCompletion:
            {
                // Example of TEXT COMPLETION

                // Locate beginning of current word
                const char* word_end = data->Buf + data->CursorPos;
                const char* word_start = word_end;
                while (word_start > data->Buf)
                {
                    const char c = word_start[-1];
                    if (c == ' ' || c == '\t' || c == ',' || c == ';')
                        break;
                    word_start--;
                }

                // Build a list of candidates
                ImVector<const char*> candidates;
                for (int i = 0; i < Commands.Size; i++)
                    if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
                        candidates.push_back(Commands[i]);

                if (candidates.Size == 0)
                {
                    // No match
                    AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
                }
                else if (candidates.Size == 1)
                {
                    // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
                    data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
                    data->InsertChars(data->CursorPos, candidates[0]);
                    data->InsertChars(data->CursorPos, " ");
                }
                else
                {
                    // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
                    int match_len = (int)(word_end - word_start);
                    for (;;)
                    {
                        int c = 0;
                        bool all_candidates_matches = true;
                        for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
                            if (i == 0)
                                c = toupper(candidates[i][match_len]);
                            else if (c == 0 || c != toupper(candidates[i][match_len]))
                                all_candidates_matches = false;
                        if (!all_candidates_matches)
                            break;
                        match_len++;
                    }

                    if (match_len > 0)
                    {
                        data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
                        data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
                    }

                    // List matches
                    AddLog("Possible matches:\n");
                    for (int i = 0; i < candidates.Size; i++)
                        AddLog("- %s\n", candidates[i]);
                }

                break;
            }
        case ImGuiInputTextFlags_CallbackHistory:
            {
                // Example of HISTORY
                const int prev_history_pos = HistoryPos;
                if (data->EventKey == ImGuiKey_UpArrow)
                {
                    if (HistoryPos == -1)
                        HistoryPos = History.Size - 1;
                    else if (HistoryPos > 0)
                        HistoryPos--;
                }
                else if (data->EventKey == ImGuiKey_DownArrow)
                {
                    if (HistoryPos != -1)
                        if (++HistoryPos >= History.Size)
                            HistoryPos = -1;
                }

                // A better implementation would preserve the data on the current input line along with cursor position.
                if (prev_history_pos != HistoryPos)
                {
                    const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
                    data->DeleteChars(0, data->BufTextLen);
                    data->InsertChars(0, history_str);
                }
            }
        }
        return 0;
    }
};

static void ShowExampleAppConsole(bool* p_open)
{
    static ExampleAppConsole console;
    console.Draw("Example: Console", p_open);
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
//-----------------------------------------------------------------------------

// Usage:
//  static ExampleAppLog my_log;
//  my_log.AddLog("Hello %d world\n", 123);
//  my_log.Draw("title");
struct ExampleAppLog
{
    ImGuiTextBuffer     Buf;
    ImGuiTextFilter     Filter;
    ImVector<int>       LineOffsets;        // Index to lines offset
    bool                ScrollToBottom;

    void    Clear()     { Buf.clear(); LineOffsets.clear(); }

    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
    {
        int old_size = Buf.size();
        va_list args;
        va_start(args, fmt);
        Buf.appendfv(fmt, args);
        va_end(args);
        for (int new_size = Buf.size(); old_size < new_size; old_size++)
            if (Buf[old_size] == '\n')
                LineOffsets.push_back(old_size);
        ScrollToBottom = true;
    }

    void    Draw(const char* title, bool* p_open = NULL)
    {
        ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver);
        if (!ImGui::Begin(title, p_open))
        {
            ImGui::End();
            return;
        }
        if (ImGui::Button("Clear")) Clear();
        ImGui::SameLine();
        bool copy = ImGui::Button("Copy");
        ImGui::SameLine();
        Filter.Draw("Filter", -100.0f);
        ImGui::Separator();
        ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
        if (copy) ImGui::LogToClipboard();

        if (Filter.IsActive())
        {
            const char* buf_begin = Buf.begin();
            const char* line = buf_begin;
            for (int line_no = 0; line != NULL; line_no++)
            {
                const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
                if (Filter.PassFilter(line, line_end))
                    ImGui::TextUnformatted(line, line_end);
                line = line_end && line_end[1] ? line_end + 1 : NULL;
            }
        }
        else
        {
            ImGui::TextUnformatted(Buf.begin());
        }

        if (ScrollToBottom)
            ImGui::SetScrollHereY(1.0f);
        ScrollToBottom = false;
        ImGui::EndChild();
        ImGui::End();
    }
};

// Demonstrate creating a simple log window with basic filtering.
static void ShowExampleAppLog(bool* p_open)
{
    static ExampleAppLog log;

    // Demo: add random items (unless Ctrl is held)
    static double last_time = -1.0;
    double time = ImGui::GetTime();
    if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl)
    {
        const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" };
        log.AddLog("[%s] Hello, time is %.1f, frame count is %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, ImGui::GetFrameCount());
        last_time = time;
    }

    log.Draw("Example: Log", p_open);
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
//-----------------------------------------------------------------------------

// Demonstrate create a window with multiple child windows.
static void ShowExampleAppLayout(bool* p_open)
{
    ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
    if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar))
    {
        if (ImGui::BeginMenuBar())
        {
            if (ImGui::BeginMenu("File"))
            {
                if (ImGui::MenuItem("Close")) *p_open = false;
                ImGui::EndMenu();
            }
            ImGui::EndMenuBar();
        }

        // left
        static int selected = 0;
        ImGui::BeginChild("left pane", ImVec2(150, 0), true);
        for (int i = 0; i < 100; i++)
        {
            char label[128];
            sprintf(label, "MyObject %d", i);
            if (ImGui::Selectable(label, selected == i))
                selected = i;
        }
        ImGui::EndChild();
        ImGui::SameLine();

        // right
        ImGui::BeginGroup();
            ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
                ImGui::Text("MyObject: %d", selected);
                ImGui::Separator();
                ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
            ImGui::EndChild();
            if (ImGui::Button("Revert")) {}
            ImGui::SameLine();
            if (ImGui::Button("Save")) {}
        ImGui::EndGroup();
    }
    ImGui::End();
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
//-----------------------------------------------------------------------------

// Demonstrate create a simple property editor.
static void ShowExampleAppPropertyEditor(bool* p_open)
{
    ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
    if (!ImGui::Begin("Example: Property editor", p_open))
    {
        ImGui::End();
        return;
    }

    ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API.");

    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
    ImGui::Columns(2);
    ImGui::Separator();

    struct funcs
    {
        static void ShowDummyObject(const char* prefix, int uid)
        {
            ImGui::PushID(uid);                      // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
            ImGui::AlignTextToFramePadding();  // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
            bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
            ImGui::NextColumn();
            ImGui::AlignTextToFramePadding();
            ImGui::Text("my sailor is rich");
            ImGui::NextColumn();
            if (node_open)
            {
                static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
                for (int i = 0; i < 8; i++)
                {
                    ImGui::PushID(i); // Use field index as identifier.
                    if (i < 2)
                    {
                        ShowDummyObject("Child", 424242);
                    }
                    else
                    {
                        // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
                        ImGui::AlignTextToFramePadding();
                        ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i);
                        ImGui::NextColumn();
                        ImGui::PushItemWidth(-1);
                        if (i >= 5)
                            ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
                        else
                            ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
                        ImGui::PopItemWidth();
                        ImGui::NextColumn();
                    }
                    ImGui::PopID();
                }
                ImGui::TreePop();
            }
            ImGui::PopID();
        }
    };

    // Iterate dummy objects with dummy members (all the same data)
    for (int obj_i = 0; obj_i < 3; obj_i++)
        funcs::ShowDummyObject("Object", obj_i);

    ImGui::Columns(1);
    ImGui::Separator();
    ImGui::PopStyleVar();
    ImGui::End();
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Long Text / ShowExampleAppLongText()
//-----------------------------------------------------------------------------

// Demonstrate/test rendering huge amount of text, and the incidence of clipping.
static void ShowExampleAppLongText(bool* p_open)
{
    ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
    if (!ImGui::Begin("Example: Long text display", p_open))
    {
        ImGui::End();
        return;
    }

    static int test_type = 0;
    static ImGuiTextBuffer log;
    static int lines = 0;
    ImGui::Text("Printing unusually long amount of text.");
    ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
    ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
    if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
    ImGui::SameLine();
    if (ImGui::Button("Add 1000 lines"))
    {
        for (int i = 0; i < 1000; i++)
            log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i);
        lines += 1000;
    }
    ImGui::BeginChild("Log");
    switch (test_type)
    {
    case 0:
        // Single call to TextUnformatted() with a big buffer
        ImGui::TextUnformatted(log.begin(), log.end());
        break;
    case 1:
        {
            // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
            ImGuiListClipper clipper(lines);
            while (clipper.Step())
                for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
                    ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
            ImGui::PopStyleVar();
            break;
        }
    case 2:
        // Multiple calls to Text(), not clipped (slow)
        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
        for (int i = 0; i < lines; i++)
            ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
        ImGui::PopStyleVar();
        break;
    }
    ImGui::EndChild();
    ImGui::End();
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
//-----------------------------------------------------------------------------

// Demonstrate creating a window which gets auto-resized according to its content.
static void ShowExampleAppAutoResize(bool* p_open)
{
    if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
    {
        ImGui::End();
        return;
    }

    static int lines = 10;
    ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop.");
    ImGui::SliderInt("Number of lines", &lines, 1, 20);
    for (int i = 0; i < lines; i++)
        ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
    ImGui::End();
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
//-----------------------------------------------------------------------------

// Demonstrate creating a window with custom resize constraints.
static void ShowExampleAppConstrainedResize(bool* p_open)
{
    struct CustomConstraints // Helper functions to demonstrate programmatic constraints
    {
        static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
        static void Step(ImGuiSizeCallbackData* data)   { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
    };

    static bool auto_resize = false;
    static int type = 0;
    static int display_lines = 10;
    if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Vertical only
    if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Horizontal only
    if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
    if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1),  ImVec2(500, -1));          // Width 400-500
    if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400),  ImVec2(-1, 500));          // Height 400-500
    if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);          // Always Square
    if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step

    ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
    if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
    {
        const char* desc[] =
        {
            "Resize vertical only",
            "Resize horizontal only",
            "Width > 100, Height > 100",
            "Width 400-500",
            "Height 400-500",
            "Custom: Always Square",
            "Custom: Fixed Steps (100)",
        };
        if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
        if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
        if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
        ImGui::PushItemWidth(200);
        ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
        ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
        ImGui::PopItemWidth();
        ImGui::Checkbox("Auto-resize", &auto_resize);
        for (int i = 0; i < display_lines; i++)
            ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
    }
    ImGui::End();
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
//-----------------------------------------------------------------------------

// Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
static void ShowExampleAppSimpleOverlay(bool* p_open)
{
    const float DISTANCE = 10.0f;
    static int corner = 0;
    ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE);
    ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
    if (corner != -1)
        ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
    ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background
    if (ImGui::Begin("Example: Simple Overlay", p_open, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
    {
        ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
        ImGui::Separator();
        if (ImGui::IsMousePosValid())
            ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
        else
            ImGui::Text("Mouse Position: <invalid>");
        if (ImGui::BeginPopupContextWindow())
        {
            if (ImGui::MenuItem("Custom",       NULL, corner == -1)) corner = -1;
            if (ImGui::MenuItem("Top-left",     NULL, corner == 0)) corner = 0;
            if (ImGui::MenuItem("Top-right",    NULL, corner == 1)) corner = 1;
            if (ImGui::MenuItem("Bottom-left",  NULL, corner == 2)) corner = 2;
            if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
            if (p_open && ImGui::MenuItem("Close")) *p_open = false;
            ImGui::EndPopup();
        }
    }
    ImGui::End();
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
//-----------------------------------------------------------------------------

// Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
// This apply to all regular items as well. Read FAQ section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." for details.
static void ShowExampleAppWindowTitles(bool*)
{
    // By default, Windows are uniquely identified by their title.
    // You can use the "##" and "###" markers to manipulate the display/ID.

    // Using "##" to display same title but have unique identifier.
    ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
    ImGui::Begin("Same title as another window##1");
    ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
    ImGui::End();

    ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
    ImGui::Begin("Same title as another window##2");
    ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
    ImGui::End();

    // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
    char buf[128];
    sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
    ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
    ImGui::Begin(buf);
    ImGui::Text("This window has a changing title.");
    ImGui::End();
}

//-----------------------------------------------------------------------------
// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
//-----------------------------------------------------------------------------

// Demonstrate using the low-level ImDrawList to draw custom shapes.
static void ShowExampleAppCustomRendering(bool* p_open)
{
    ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver);
    if (!ImGui::Begin("Example: Custom rendering", p_open))
    {
        ImGui::End();
        return;
    }

    // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
    // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
    // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
    // In this example we are not using the maths operators!
    ImDrawList* draw_list = ImGui::GetWindowDrawList();

    // Primitives
    ImGui::Text("Primitives");
    static float sz = 36.0f;
    static float thickness = 4.0f;
    static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
    ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
    ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
    ImGui::ColorEdit3("Color", &col.x);
    {
        const ImVec2 p = ImGui::GetCursorScreenPos();
        const ImU32 col32 = ImColor(col);
        float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
        for (int n = 0; n < 2; n++)
        {
            float curr_thickness = (n == 0) ? 1.0f : thickness;
            draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, curr_thickness); x += sz+spacing;
            draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing;
            draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing;
            draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, curr_thickness); x += sz+spacing;
            draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, curr_thickness); x += sz+spacing;
            draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y   ), col32, curr_thickness); x += sz+spacing;   // Horizontal line (note: drawing a filled rectangle will be faster!)
            draw_list->AddLine(ImVec2(x, y), ImVec2(x,    y+sz), col32, curr_thickness); x += spacing;      // Vertical line (note: drawing a filled rectangle will be faster!)
            draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, curr_thickness); x += sz+spacing;   // Diagonal line
            draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, curr_thickness);
            x = p.x + 4;
            y += sz+spacing;
        }
        draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing;
        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing;
        draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing;
        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+thickness), col32); x += sz+spacing;          // Horizontal line (faster than AddLine, but only handle integer thickness)
        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+thickness, y+sz), col32); x += spacing+spacing;     // Vertical line (faster than AddLine, but only handle integer thickness)
        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+1, y+1), col32);          x += sz;                  // Pixel (faster than AddLine)
        draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), IM_COL32(0,0,0,255), IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255));
        ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));
    }
    ImGui::Separator();
    {
        static ImVector<ImVec2> points;
        static bool adding_line = false;
        ImGui::Text("Canvas example");
        if (ImGui::Button("Clear")) points.clear();
        if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
        ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");

        // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
        // But you can also draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
        // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
        ImVec2 canvas_pos = ImGui::GetCursorScreenPos();            // ImDrawList API uses screen coordinates!
        ImVec2 canvas_size = ImGui::GetContentRegionAvail();        // Resize canvas to what's available
        if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
        if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
        draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50, 50, 50, 255), IM_COL32(50, 50, 60, 255), IM_COL32(60, 60, 70, 255), IM_COL32(50, 50, 60, 255));
        draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255, 255, 255, 255));

        bool adding_preview = false;
        ImGui::InvisibleButton("canvas", canvas_size);
        ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
        if (adding_line)
        {
            adding_preview = true;
            points.push_back(mouse_pos_in_canvas);
            if (!ImGui::IsMouseDown(0))
                adding_line = adding_preview = false;
        }
        if (ImGui::IsItemHovered())
        {
            if (!adding_line && ImGui::IsMouseClicked(0))
            {
                points.push_back(mouse_pos_in_canvas);
                adding_line = true;
            }
            if (ImGui::IsMouseClicked(1) && !points.empty())
            {
                adding_line = adding_preview = false;
                points.pop_back();
                points.pop_back();
            }
        }
        draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), true);      // clip lines within the canvas (if we resize it, etc.)
        for (int i = 0; i < points.Size - 1; i += 2)
            draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i + 1].x, canvas_pos.y + points[i + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
        draw_list->PopClipRect();
        if (adding_preview)
            points.pop_back();
    }
    ImGui::End();
}

// End of Demo code
#else

void ImGui::ShowDemoWindow(bool*) {}
void ImGui::ShowUserGuide() {}
void ImGui::ShowStyleEditor(ImGuiStyle*) {}

#endif
