diff --git a/.gitignore b/.gitignore index 7003d77..0874f4d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ # Qt *.pro.user build-* +*.txt.user + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6ef6d71 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +project(model-ghdl) +cmake_minimum_required(VERSION 2.8) +aux_source_directory(. SRC_LIST) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK3 REQUIRED gtk+-3.0) + +include_directories(${GTK3_INCLUDE_DIRS}) +link_directories(${GTK3_LIBRARY_DIRS}) +add_definitions(${GTK3_CFLAGS_OTHER}) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) + +target_link_libraries(${PROJECT_NAME} ${GTK3_LIBRARIES}) + + +add_custom_command( + TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ln -sf ${PROJECT_NAME} vsim + COMMAND ln -sf ${PROJECT_NAME} vcom + COMMAND ln -sf ${PROJECT_NAME} vmap + COMMAND ln -sf ${PROJECT_NAME} vdel + COMMAND ln -sf ${PROJECT_NAME} vlib +) diff --git a/README.md b/README.md index 0bc0382..7ae2ae9 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,3 @@ model-ghdl ========== A wrapper for GHDL to make it look like Mentor's ModelSim. Helpful for use with programs like Sigasi. - -## Tips -Add the following arguments in Sigasi: - -### vsim -* ```-ghdl "--std=08"``` to enable VHDL 2008 support (if any problems occur) -* ```-gtksave "/path/to/your/gtkw-directory"``` to automatically load a specific wave layout (```/```) diff --git a/gui.c b/gui.c new file mode 100644 index 0000000..3694926 --- /dev/null +++ b/gui.c @@ -0,0 +1,86 @@ +#include "gui.h" + +#define true 1 +#define false 0 + +int gui_init(int *argc, char ***argv) { + gtk_init (argc, argv); + return 0; +} + +int showMessage(int message_type, char *text, char *defaultText, char **reply) { + GtkWidget *window; + GtkWidget *entry; + GtkWidget *buttonOkay; + GtkWidget *buttonCancel; + GtkWidget *buttonBox; + GtkWidget *mainBox; + GtkWidget *label; + char *entryText; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "Meow"); + + label = gtk_label_new(text); + gtk_widget_show(label); + + entry = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(entry), (char*) defaultText); + g_signal_connect (entry, "activate", + G_CALLBACK(okay), entry); + gtk_widget_show(entry); + + buttonOkay = gtk_button_new_with_label("Okay!"); + gtk_widget_show(buttonOkay); + buttonCancel = gtk_button_new_with_label("Cancel"); + gtk_widget_show(buttonCancel); + + buttonBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); + gtk_box_pack_start(GTK_BOX(buttonBox), buttonCancel, true, true, 0); + gtk_box_pack_start(GTK_BOX(buttonBox), buttonOkay, true, true, 0); + g_signal_connect (buttonOkay, "clicked", + G_CALLBACK(okay), entry); + gtk_widget_show(buttonBox); + + mainBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); + gtk_box_pack_start(GTK_BOX(mainBox), label, true, true, 0); + gtk_box_pack_start(GTK_BOX(mainBox), entry, true, true, 0); + gtk_box_pack_start(GTK_BOX(mainBox), buttonBox, true, true, 0); + gtk_widget_show(mainBox); + + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + gtk_container_add(GTK_CONTAINER(window), mainBox); + gtk_widget_show (window); + + gtk_main(); + + entryText = (char*) gtk_entry_get_text(GTK_ENTRY(entry)); + if (entryText[0] == 0) { + return false; + } + else { + *reply = realloc(*reply, sizeof(char)*strlen(entryText)); + if (*reply != NULL) + strcpy(*reply, entryText); + return true; + } + + + gtk_widget_destroy(window); +} + +static void okay( GtkWidget *widget, + gpointer data ) +{ + //g_print ("TEXT = %s\n", gtk_entry_get_text(GTK_ENTRY(data))); + gtk_main_quit(); +} + +static void cancel( GtkWidget *widget, + gpointer data ) +{ + gtk_entry_set_text(GTK_ENTRY(data), ""); + gtk_main_quit(); +} diff --git a/gui.h b/gui.h new file mode 100644 index 0000000..2313589 --- /dev/null +++ b/gui.h @@ -0,0 +1,13 @@ +#ifndef GUI_H +#define GUI_H +#include +#include +#include + +int gui_init(int *argc, char ***argv); +int showMessage(int message_type, char *text, char *defaultText, char **reply); + +// Slots +static void okay( GtkWidget *widget, gpointer data ); + +#endif // GUI_H diff --git a/main.c b/main.c new file mode 100644 index 0000000..c98144c --- /dev/null +++ b/main.c @@ -0,0 +1,186 @@ +#include +#include +#include "gui.h" + +#ifndef PROGRAM_REVISION +#define PROGRAM_REVISION "#unknown" +#endif + +#define PROG_VCOM 0 +#define PROG_VSIM 1 +#define PROG_UNKNOWN 255 + +#define K *1024 +#define M K K +#define G M K + +#define ISOPT(cmd) (strcmp(argv[i], cmd) == 0) +#define GETOPT(cmd) (strcmp(argv[i], cmd) == 0) && (++i < argc) + +const char *laststrstr (const char *__haystack, const char *__needle); +int get_application(const char *call); +int vsim(int argc, char **argv); +int vcom(int argc, char **argv); +int run_ghdl(char *command, ...); +char* append_string(char **dest, const char *src); + +int run_ghdl(char *command, ...) { + FILE *proc; + char buf[1 K]; + char cmd[1 K]; + + char *arr[4]; + char *start; + char *ptr; + int arrc; + + va_list argptr; + va_start(argptr, command); + vsprintf(cmd, command, argptr); + va_end(argptr); + + printf("RUN: %s\n", cmd); + proc = popen(cmd, "r"); + + if (proc == NULL) { + printf("Error: Could not invoke GHDL/GtkWave.\n"); + return 1; + } + + // ../blink/src/top.vhd:32:19: no declaration for "counter_i2" + // v + // ** Error: /tmp/filename.vhd(32): (vcom-1136) Unknown identifier "counter_i2". + + while(fgets(buf, sizeof(buf), proc)!=NULL){ + ptr = buf; + start = buf; + arrc = 0; + + do { // Search for EOL + if (arrc < 4 && (*ptr == ':' || *ptr == '\0')) { + *ptr++ = 0; + arr[arrc++] = start; + start = ptr; + } + } while (*ptr++ != '\0'); + + if (arrc == 4) { + printf("** Error: %s(%s): (ghdl) %s", arr[0], arr[1], arr[3]); + } + else { + printf("** ghdl: %s", buf); + } + } + printf("\n"); + + return pclose(proc); +} + +int vsim(int argc, char **argv) +{ + int ret; + char *text = NULL; + + gui_init(&argc, &argv); + ret = showMessage(0, "Enter the simulation time: ", "100 ns", &text); + printf("%d: %p: %s\n", ret, text, text); +} + +int vcom(int argc, char **argv) +{ + int i; + int slen = 0; + char tempdir[1 K]; + char *work; + char *files = NULL; + + if (!getcwd(tempdir, sizeof(tempdir))) { // Default compile dir is cwd + fprintf(stderr, "Error: Could not invoke GHDL!\n"); + return 1; + } + + for (i=1; i < argc; ++i) { + if (GETOPT("-work")) { + work = argv[i]; + } + else if (GETOPT("-compiledir")) { + strcpy(tempdir, argv[i]); + } + else if (argv[i][0] != '-'){ // VHDL file + slen += strlen(argv[i]) + 1; + files = realloc(files, slen * sizeof(char)); + strcat(files, " "); + strcat(files, argv[i]); + } + } + + run_ghdl("ghdl -s %s 2>&1", files); + + + free(files); + + printf("DONE.\n"); +} + + +char* append_string(char **dest, const char *src) { + if (*dest == NULL) { + *dest = malloc(strlen(src) * sizeof(char)); + if (*dest == NULL) + return NULL; + *dest[0] = 0; + } + else { + *dest = realloc(*dest, (strlen(*dest) + strlen(src)) * sizeof(char)); + } + + strcat(*dest, src); + return *dest; +} + +int main(int argc, char **argv) +{ + int app; + printf ("model-ghdl revision %s, compiled on %s.\n", PROGRAM_REVISION, __DATE__); + + app = get_application(argv[0]); + + if (app == PROG_VCOM) { + return vcom(argc, argv); + } + else if (app == PROG_VSIM) { + return vsim(argc, argv); + } + + return 255; +} + +// Detects which function to call depending on the program name in argv[0] +int get_application(const char *call) { + char *pos; + pos = (char*) laststrstr(call, "/") + 1; + if (strcmp(pos, "vcom") == 0) { + return PROG_VCOM; + } + else if (strcmp(pos, "vsim") == 0) { + return PROG_VCOM; + } + else { + fprintf(stderr, "[E] Program not recognized: %s\n", pos); + return PROG_UNKNOWN; + } +} + +// Returns the string after the last occurence of __needle +const char *laststrstr (const char *__haystack, const char *__needle) { + char *pos, *realPos; + char *haystack; + haystack = (char*) __haystack; + pos = (char*) __haystack; + while (pos != NULL) { + realPos = pos; + pos = strstr(haystack, __needle); + haystack = pos + 1; + } + return realPos; +} diff --git a/vcom/main.cpp b/vcom/main.cpp deleted file mode 100644 index 087ce90..0000000 --- a/vcom/main.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -// #define DEBUG_EN DEBUG_EN - - -/* - * -> /tmp/SigasiCompileCache822149657706169838/blink/vcom > /home/markus/Downloads/Libero/install/Model/modeltech/linuxacoem/vcom -2008 -work design -modelsimini /tmp/SigasiCompileCache822149657706169838/blink/vcom/modelsim.ini /home/markus/workspaceSigasi/blink/src/top.vhd -Model Technology ModelSim Microsemi vcom 10.3a Compiler 2014.04 Apr 15 2014 -Start time: 19:57:50 on Jan 18,2015 -vcom -2008 -work design -modelsimini /tmp/SigasiCompileCache822149657706169838/blink/vcom/modelsim.ini /home/markus/workspaceSigasi/blink/src/top.vhd --- Loading package STANDARD --- Loading package TEXTIO --- Loading package std_logic_1164 --- Loading package NUMERIC_STD --- Compiling entity top --- Compiling architecture RTL of top -** Error: /home/markus/workspaceSigasi/blink/src/top.vhd(32): (vcom-1136) Unknown identifier "counter_i2". -** Error: /home/markus/workspaceSigasi/blink/src/top.vhd(33): VHDL Compiler exiting -End time: 19:57:50 on Jan 18,2015, Elapsed time: 0: 0: 0 -Errors: 2, Warnings: 0 - - - -COMPILATION: -> ghdl -i --warn-no-vital-generic --workdir=. --work=design ../blink/src/ *.vhd -> ghdl -m --warn-no-vital-generic --workdir=. --work=work top -../blink/src/top.vhd:32:19: no declaration for "counter_i2" - - -SYNTAX CHECKING: -> ghdl -s --warn-no-vital-generic --workdir=. --work=design ../blink/src/ *.vhd -../blink/src/top.vhd:32:19: no declaration for "counter_i2" - - -echo "EXTERNAL: $# $@" - -vars=`echo "$@" | sed "s/-work /-work=/g"`; - -*/ - - -using namespace std; - -#define ISOPT(cmd) (string(argv[i]) == cmd) -#define GETOPT(cmd) (string(argv[i]) == cmd) && (++i < argc) - -int run(string args); - -int run(string args) { - FILE *proc; - char buf[512]; - vector < string > result; - - proc = popen(args.c_str(), "r"); - - if (proc == NULL) { - cerr << "Error: Could not invoke GHDL." << endl; - return 1; - } - - while(fgets(buf, sizeof(buf), proc)!=NULL){ - //cout << buf; - string temp = ""; - char *ptr = buf; - - result.clear(); - - while (*ptr != '\0') { - if (*ptr == ':' || *ptr == '\0') { - result.push_back(temp); - temp = ""; - } - else { - temp.append(" "); - temp[temp.length()-1] = *ptr; - } - ptr++; - } - result.push_back(temp); - - if (result.size() == 4) { - cout << "** Error: " << result[0] << "(" << result[1] << "):" << result[3]; - } - else { - cout << buf; - } - } - pclose(proc); - return 0; -} - -int main(int argc, char **argv) -{ - int i; - string work = ""; // Current library - string vhdl = ""; // Input VHDL files - string vhdlver = ""; // VHDL Version - string ghdlargs = ""; // Additional GHDL parameters - char tempdir[256] = ""; // Compile dir - - if (!getcwd(tempdir, sizeof(tempdir))) { - cerr << "Error getting current working dir!" << endl; - return 1; - } - - for (i=1; i < argc; ++i) { - if (GETOPT("-work")) { - work = argv[i]; - //++i; - } - else if (GETOPT("-compiledir")) { - strcpy(tempdir, argv[i]); - } - else if (ISOPT("-87")) { - vhdlver = "--std=87"; - } - else if (ISOPT("-93")) { - vhdlver = "--std=93"; - } - else if (ISOPT("-93c")) { - vhdlver = "--std=93c"; - } - else if (ISOPT("-2000")) { - vhdlver = "--std=00"; - } - else if (ISOPT("-2002")) { - vhdlver = "--std=02"; - } - else if (ISOPT("-2008")) { - cerr << "WARN: VHDL 2008 is not yet fully supported by GHDL." << endl; - vhdlver = "--std=08"; - } - else if (GETOPT("-ghdl")) { - ghdlargs += string(argv[i]) + " "; - } - else if (GETOPT("-modelsimini")) { - // Not used - // ++i; // But skip param - } - else { - if (argv[i][0] == '-') { - cerr << "INFO: Unknown command line opt: " << argv[i] << endl; - } - else { - vhdl.append(argv[i]); - vhdl.append(" "); - } - } - } - -#ifdef DEBUG_EN - cout << "\n\nVCOM CALL PARSED:" << endl; - cout << "\twork=" << work << endl; - cout << "\tvhdl=" << vhdl << endl; - cout << "\ttempdir=" << tempdir << endl; -#endif - - if (work == "" || vhdl == "" || string(tempdir) == "") { - cerr << "Error: Incomplete/Unsupported vcom call." << endl; - return 2; - } - - // Write temp path to /tmp - ofstream myfile; - myfile.open ("/tmp/ghdl-workdir"); - myfile << tempdir; - myfile.flush(); - myfile.close(); - - string cargs = "ghdl -i " + vhdlver + " --warn-no-vital-generic " + ghdlargs + " --workdir=" + string(tempdir) + " --work=" + work + " " + vhdl + " 2>&1"; - string sargs = "ghdl -s " + vhdlver + " --warn-no-vital-generic " + ghdlargs + " --workdir=" + string(tempdir) + " --work=" + work + " " + vhdl + " 2>&1"; - -#ifdef DEBUG_EN - cout << "RUN: " << cargs << endl; - cout << "RUN: " << sargs << endl; -#endif - // Launch GHDL - if (run(cargs) || run(sargs)) { - cerr << "** Error: Error in model-ghdl." << endl; - } - return 0; -} - diff --git a/vcom/vcom.pro b/vcom/vcom.pro deleted file mode 100644 index c4a1a92..0000000 --- a/vcom/vcom.pro +++ /dev/null @@ -1,8 +0,0 @@ -TEMPLATE = app -CONFIG += console -CONFIG -= app_bundle -CONFIG -= qt - -SOURCES += main.cpp - -#QMAKE_CXXFLAGS += -std=c++11 diff --git a/vsim/main.cpp b/vsim/main.cpp deleted file mode 100644 index 81c5aa7..0000000 --- a/vsim/main.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -// #define DEBUG_EN DEBUG_EN - -using namespace std; - -// Source: vsim -gui design.top(RTL) -// Target: ghdl -m --warn-no-vital-generic --workdir=simu --work=work testb_file -// ./testb_file --stop-time=500ns --vcdgz=testb_file.vcdgz -// gunzip --stdout testb_file.vcdgz | gtkwave --vcd - -int run(string args); - -int run(string args) { - FILE *proc; - char buf[512]; - vector < string > result; - - proc = popen(args.c_str(), "r"); - - if (proc == NULL) { - cerr << "Error: Could not invoke GHDL/GtkWave." << endl; - return 1; - } - - while(fgets(buf, sizeof(buf), proc)!=NULL){ - cout << buf; - } - - return pclose(proc); -} - -string getSimulationTime() { // Very crude but works (for a proof-of-concept anyway^^) - FILE *proc; - char buf[512]; - vector < string > result; - string defaultValue = "100ns"; - - ifstream myfile; - char fileTemp[128]; - myfile.open ("/tmp/ghdl-simtime"); - myfile.getline(fileTemp, sizeof(fileTemp)); - myfile.close(); - if (string(fileTemp) != "") - defaultValue = string(fileTemp); - - string temp = "zenity --entry --text \"Enter the duration:\" --title \"Simulation time\" --entry-text=\"" + defaultValue + "\""; - proc = popen(temp.c_str(), "r"); - - if (proc == NULL) { - cerr << "Error: Could not invoke zenity." << endl; - return ""; - } - - while(fgets(buf, sizeof(buf), proc)!=NULL){ - cout << buf; - } - - - defaultValue.clear(); - char *ptr = buf; - while (*ptr != '\0' && *ptr != '\n') { - defaultValue.append(" "); - defaultValue[defaultValue.length()-1] = *ptr; - ptr++; - } - - if (pclose(proc)) { - defaultValue = ""; - } - else { - ofstream myfile; - myfile.open ("/tmp/ghdl-simtime"); - myfile << defaultValue; - myfile.flush(); - myfile.close(); - } - - return defaultValue; -} - -#define ISOPT(cmd) (string(argv[i]) == cmd) -#define GETOPT(cmd) (string(argv[i]) == cmd) && (++i < argc) - -int main(int argc, char **argv) { - string top = ""; - string work = ""; - string simtime = ""; - string ghdlargs = ""; - string wvargs = ""; - string gtkargs = ""; - string gtksave = ""; - string vhdlver = ""; // VHDL Version - int i; - char tempdir[256] = ""; // Compile dir - - ifstream myfile; - myfile.open ("/tmp/ghdl-workdir"); - myfile.getline(tempdir, sizeof(tempdir)); - myfile.close(); - - for (i=1; i < argc; ++i) { - if (ISOPT("-gui")) { - - } - else if (GETOPT("-compiledir")) { - strcpy(tempdir, argv[i]); - } - else if (ISOPT("-87")) { - vhdlver = "--std=87"; - } - else if (ISOPT("-93")) { - vhdlver = "--std=93"; - } - else if (ISOPT("-93c")) { - vhdlver = "--std=93c"; - } - else if (ISOPT("-2000")) { - vhdlver = "--std=00"; - } - else if (ISOPT("-2002")) { - vhdlver = "--std=02"; - } - else if (ISOPT("-2008")) { - cerr << "WARN: VHDL 2008 is not yet fully supported by GHDL." << endl; - vhdlver = "--std=08"; - } - else if (GETOPT("-ghdl")) { - ghdlargs += string(argv[i]) + " "; - } - else if (GETOPT("-rargs")) { - wvargs = argv[i]; - } - else if (GETOPT("-gtkwave")) { - gtkargs = argv[i]; - } - else if (GETOPT("-gtksave")) { - gtksave = argv[i]; - } - else { - if (argv[i][0] == '-') { - cerr << "INFO: Unknown command line opt: " << argv[i] << endl; - } - else { - top.append(argv[i]); - top.append(" "); - } - } - } - - - // -gui work.toplevel(RTL) - string temp = ""; - for (unsigned int i=0; i < top.length(); ++i) { - if (top.at(i) >= 'A' && top.at(i) <= 'Z') - top.at(i) = top.at(i) - ('A'-'a'); // convert to lower case - - if (top.at(i) == '.') { - work = temp; - temp = ""; - } - else if (top.at(i) == '(') { - top = temp; - temp = ""; - break; - } - else { - temp.append(" "); - temp[temp.length()-1] = top.at(i); - } - } - -#ifdef DEBUG_EN - cout << "\n\nVSIM CALL PARSED:" << endl; - cout << "\twork=" << work << endl; - cout << "\ttop=" << top<< endl; - cout << "\ttempdir=" << tempdir << endl; -#endif - - if (work == "" || top == "" || string(tempdir) == "") { - cerr << "Error: Incomplete/Unsupported vsim call." << endl; - return 2; - } - - - //bool ex = false; - //while (!ex) { - cout << "Compiling..." << endl; - string cargs = "cd " + string(tempdir) + "; ghdl -m " + vhdlver + " " + ghdlargs + " --workdir=" + string(tempdir) + " --work=" + work + " " + top; -#ifdef DEBUG_EN - cout << "RUN: " << cargs << endl; -#endif - if (run(cargs)) { - cerr << "Error: Compilation failed." << endl; - run("zenity --error --text \"Compilation failed.\""); - } - else { - cout << "done." << endl; - cargs = ""; - string st = getSimulationTime(); - if (st != "") { - cout << "Simulating..." << endl; -#ifdef DEBUG_EN - cout << "RUN: " << "cd " + string(tempdir) + "; ./" + top + " " + wvargs + " --stop-time=" + st + " --wave=" + top + ".ghw" << endl; -#endif - if (run("cd " + string(tempdir) + "; ./" + top + " " + wvargs + " --stop-time=" + st + " --wave=" + top + ".ghw")) { - cerr << "Error: Simulation failed." << endl; - } - else { - cout << "==> All done!" << endl; - if (gtksave != "") { - gtkargs += " --save=\"" + gtksave + "/" + top + ".gtkw\""; - } - string wv = "gtkwave " + string(tempdir) + "/" + top + ".ghw " + gtkargs + " &"; - if (run("pidof gtkwave")) { - if (system(wv.c_str())) { - cerr << "Error: GtkWave failed."; - } - else { - cout << "GtkWave started." << endl; - } - } - } - } - } - //} - - //cout << "Simulation ended." << endl; - return 0; -} - diff --git a/vsim/vsim.pro b/vsim/vsim.pro deleted file mode 100644 index d850e99..0000000 --- a/vsim/vsim.pro +++ /dev/null @@ -1,8 +0,0 @@ -TEMPLATE = app -CONFIG += console -CONFIG -= app_bundle -CONFIG -= qt - - -SOURCES += main.cpp -