mirror of
https://github.com/cclassic/model-ghdl
synced 2025-11-06 03:09:32 +01:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 55bf73e52d | |||
| ef6c65d20d | |||
| 55105018aa | |||
| bccb210a8f | |||
|
|
fad1f6433c | ||
|
|
964e9fd055 | ||
|
|
cee0976240 | ||
|
|
fde1671c08 | ||
|
|
7a8226f44d | ||
|
|
8c5bdd7c60 | ||
|
|
d0c20c6e01 | ||
|
|
b3171fbbb7 | ||
|
|
f304d611a8 | ||
|
|
1df04509a4 | ||
|
|
710ad3cb01 | ||
|
|
5bb82eb499 | ||
|
|
171277632c | ||
|
|
fe7a3f7225 | ||
|
|
59e3a4855c | ||
|
|
a62951aed2 | ||
|
|
7189e18c19 | ||
|
|
ea2dffbb6d | ||
|
|
23a642820e | ||
|
|
fdf04cb659 | ||
|
|
37b4af2913 | ||
|
|
ad960b7243 | ||
|
|
a989b7bb06 | ||
|
|
9bf6c625f4 | ||
|
|
4f7478b8c1 | ||
|
|
53f3e187a4 | ||
|
|
4a64ba77a0 | ||
|
|
7f211ef8a3 | ||
|
|
436ef08df0 | ||
|
|
cc44efb787 | ||
|
|
5c4b51a3ae | ||
|
|
e85e7d7516 | ||
|
|
5969ad5848 | ||
|
|
d65c627efa |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,3 +15,5 @@
|
|||||||
# Qt
|
# Qt
|
||||||
*.pro.user
|
*.pro.user
|
||||||
build-*
|
build-*
|
||||||
|
*.txt.user
|
||||||
|
|
||||||
|
|||||||
27
CMakeLists.txt
Normal file
27
CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
install (TARGETS model-ghdl DESTINATION bin)
|
||||||
|
install (FILES vsim vcom vmap vdel vlib DESTINATION bin)
|
||||||
59
README.md
59
README.md
@@ -3,9 +3,58 @@ model-ghdl
|
|||||||
|
|
||||||
A wrapper for GHDL to make it look like Mentor's ModelSim. Helpful for use with programs like Sigasi.
|
A wrapper for GHDL to make it look like Mentor's ModelSim. Helpful for use with programs like Sigasi.
|
||||||
|
|
||||||
## Tips
|
Compiling and use
|
||||||
Add the following arguments in Sigasi:
|
-----------------
|
||||||
|
First install ghdl from [github](https://github.com/tgingold/ghdl/) and install GtkWave. Model-ghdl expects to find the ghdl and gtkwave executables in the system $PATH.
|
||||||
|
|
||||||
### vsim
|
Then, to compile the wrapper, simply do the following:
|
||||||
* ```-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 (```<path>/<top_entity.gtkw>```)
|
git clone https://github.com/cclassic/model-ghdl
|
||||||
|
cmake .
|
||||||
|
make
|
||||||
|
```
|
||||||
|
The five modelsim applications should now be present in the current folder as symlinks along with a model-ghdl binary. Either install these into your path or point your IDE to the location of the files.
|
||||||
|
|
||||||
|
VCOM
|
||||||
|
----
|
||||||
|
### Original commands
|
||||||
|
* -work *top*: Set top level
|
||||||
|
* -workdir *dir*: Set working directory
|
||||||
|
* -87, -93, -93c, -2000, -2002, -2008: Set VHDL version
|
||||||
|
|
||||||
|
### Additional commands
|
||||||
|
* -ghdl *param*: Supply these arguments directly to GHDL (can be used multiple times)
|
||||||
|
* -no-precompile: Compile the files not until calling vsim. (Faster syntax check, but longer wait time for the simulation to start.)
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
* *cwd* is expected to be the compile directory
|
||||||
|
* Recommended arguments: -ghdl --ieee=synopsys -ghdl -fexplicit -ghdl -frelaxed-rules -ghdl -P[/path/to/lib](https://github.com/tgingold/ghdl/tree/master/libraries/vendors)
|
||||||
|
|
||||||
|
VSIM
|
||||||
|
----
|
||||||
|
### Original commands
|
||||||
|
* -gui *work.toplevel(RTL)*: Set toplevel and work library
|
||||||
|
|
||||||
|
### Additional commands
|
||||||
|
* -ghdl *param*: Supply these arguments directly to GHDL (can be used multiple times)
|
||||||
|
* -gtkwprefix *prefix*: Prefix for the .gtkw save file. Path will be $cwd/$prefix$toplevel.gtkw
|
||||||
|
* -type *extension*: Set simulation output file type. Can be: ghw (default), vcd or fst
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
* *cwd* is expected to be the source directory (used for .gtkw save path)
|
||||||
|
* Recommended arguments: -gtkwprefix gtkwave/ -ghdl --ieee=synopsys -ghdl -fexplicit -ghdl -frelaxed-rules -ghdl -P[/path/to/lib](https://github.com/tgingold/ghdl/tree/master/libraries/vendors)
|
||||||
|
|
||||||
|
|
||||||
|
VMAP
|
||||||
|
----
|
||||||
|
No function.
|
||||||
|
|
||||||
|
|
||||||
|
VLIB
|
||||||
|
----
|
||||||
|
No function.
|
||||||
|
|
||||||
|
|
||||||
|
VDEL
|
||||||
|
----
|
||||||
|
No function.
|
||||||
|
|||||||
35
arch/PKGBUILD
Normal file
35
arch/PKGBUILD
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Maintainer: Markus Koch <CClassicVideos@aol.com>
|
||||||
|
|
||||||
|
pkgname=model-ghdl
|
||||||
|
pkgver=59.cee0976
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc='A wrapper for ghdl to make it look like modelsim.'
|
||||||
|
arch=('i686' 'x86_64')
|
||||||
|
url='https://github.com/cclassic/model-ghdl'
|
||||||
|
license=('GPL')
|
||||||
|
depends=('gtk3')
|
||||||
|
makedepends=('cmake' 'git')
|
||||||
|
source=("model-ghdl::git://github.com/cclassic/model-ghdl.git")
|
||||||
|
sha1sums=('SKIP')
|
||||||
|
|
||||||
|
pkgver() {
|
||||||
|
cd "$srcdir/model-ghdl"
|
||||||
|
echo -n $(git log|grep -e ^commit|wc -l).
|
||||||
|
echo $(git log | head -n 1 | sed "s/.* //g" | head -c 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
cd "$srcdir/model-ghdl"
|
||||||
|
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .
|
||||||
|
#-DCMAKE_C_FLAGS=-DPROGRAM_REVISION="#${pkgver}";
|
||||||
|
|
||||||
|
make
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "$srcdir/model-ghdl"
|
||||||
|
|
||||||
|
make DESTDIR="${pkgdir}" install
|
||||||
|
}
|
||||||
|
|
||||||
12
arch/README.md
Normal file
12
arch/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Arch Linux Build Script
|
||||||
|
=======================
|
||||||
|
This directory contains the PKGBUILD required to compile binary distribution packages for Arch Linux.
|
||||||
|
|
||||||
|
Build instructions
|
||||||
|
------------------
|
||||||
|
On Arch, simply enter
|
||||||
|
```
|
||||||
|
$ makepkg -s
|
||||||
|
# pacman -U model-ghdl-xxxxxxx-1-arch.pkg.tar.xz
|
||||||
|
```
|
||||||
|
to install the program.
|
||||||
101
gui.c
Normal file
101
gui.c
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#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;
|
||||||
|
gboolean ret;
|
||||||
|
char *entryText;
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||||
|
gtk_window_set_title(GTK_WINDOW(window), "model-ghdl");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
buttonOkay = gtk_button_new_with_label("Okay!");
|
||||||
|
gtk_widget_show(buttonOkay);
|
||||||
|
|
||||||
|
if (MESSAGE_IS_INPUT(message_type)) {
|
||||||
|
buttonCancel = gtk_button_new_with_label("Cancel");
|
||||||
|
g_signal_connect (buttonCancel, "clicked",
|
||||||
|
G_CALLBACK(cancel), entry);
|
||||||
|
gtk_widget_show(buttonCancel);
|
||||||
|
|
||||||
|
gtk_widget_show(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
|
||||||
|
if (MESSAGE_IS_INPUT(message_type)) {
|
||||||
|
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, 10);
|
||||||
|
if (MESSAGE_IS_INPUT(message_type)) {
|
||||||
|
gtk_box_pack_start(GTK_BOX(mainBox), entry, true, true, 0);
|
||||||
|
}
|
||||||
|
gtk_box_pack_start(GTK_BOX(mainBox), buttonBox, false, false, 0);
|
||||||
|
gtk_widget_show(mainBox);
|
||||||
|
|
||||||
|
g_signal_connect (window, "destroy",
|
||||||
|
G_CALLBACK (cancel), NULL);
|
||||||
|
|
||||||
|
gtk_container_add(GTK_CONTAINER(window), mainBox);
|
||||||
|
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
|
||||||
|
gtk_window_set_default_size(GTK_WINDOW(window), 320, 10);
|
||||||
|
gtk_window_present(GTK_WINDOW(window));
|
||||||
|
|
||||||
|
gtk_main();
|
||||||
|
|
||||||
|
if (MESSAGE_IS_INPUT(message_type)) {
|
||||||
|
entryText = (char*) gtk_entry_get_text(GTK_ENTRY(entry));
|
||||||
|
if (entryText[0] == 0) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*reply = realloc(*reply, sizeof(char)*strlen(entryText));
|
||||||
|
if (*reply != NULL)
|
||||||
|
strcpy(*reply, entryText);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_destroy(window);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
19
gui.h
Normal file
19
gui.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef GUI_H
|
||||||
|
#define GUI_H
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// #define MESSAGE_INFO 0 // NYI!
|
||||||
|
#define MESSAGE_ERROR 1
|
||||||
|
#define MESSAGE_INPUT 32
|
||||||
|
#define MESSAGE_IS_INPUT(msg) ((msg >= 32) && (msg < 64))
|
||||||
|
|
||||||
|
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);
|
||||||
|
static void cancel(GtkWidget *widget, gpointer data);
|
||||||
|
|
||||||
|
#endif // GUI_H
|
||||||
560
main.c
Normal file
560
main.c
Normal file
@@ -0,0 +1,560 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
|
#ifndef PROGRAM_REVISION
|
||||||
|
#define PROGRAM_REVISION "#unknown"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#define DEBUG_ENABLED DEBUG_ENABLED
|
||||||
|
|
||||||
|
#define PROG_VCOM 0
|
||||||
|
#define PROG_VSIM 1
|
||||||
|
#define PROG_VLIB 2
|
||||||
|
#define PROG_VMAP 3
|
||||||
|
#define PROG_VDEL 4
|
||||||
|
#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 *getAfter (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, ...);
|
||||||
|
int run_simulation(char *command, ...);
|
||||||
|
int run_gtkwave(char *toplevel, char *command, ...);
|
||||||
|
char* append_string(char **dest, const char *src);
|
||||||
|
pid_t system2(const char * command, int * infp, int * outfp);
|
||||||
|
void debug( const char* format, ... );
|
||||||
|
|
||||||
|
void debug( const char* format, ... ) {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
va_list args;
|
||||||
|
// fprintf( stderr, "[D] " );
|
||||||
|
va_start( args, format );
|
||||||
|
vfprintf( stderr, format, args );
|
||||||
|
va_end( args );
|
||||||
|
// fprintf( stderr, "\n" );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thanks GreenScape
|
||||||
|
// http://stackoverflow.com/questions/22802902/how-to-get-pid-of-process-executed-with-system-command-in-c
|
||||||
|
pid_t system2(const char * command, int * infp, int * outfp)
|
||||||
|
{
|
||||||
|
int p_stdin[2];
|
||||||
|
int p_stdout[2];
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if (pipe(p_stdin) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (pipe(p_stdout) == -1) {
|
||||||
|
close(p_stdin[0]);
|
||||||
|
close(p_stdin[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if (pid < 0) {
|
||||||
|
close(p_stdin[0]);
|
||||||
|
close(p_stdin[1]);
|
||||||
|
close(p_stdout[0]);
|
||||||
|
close(p_stdout[1]);
|
||||||
|
return pid;
|
||||||
|
} else if (pid == 0) {
|
||||||
|
close(p_stdin[1]);
|
||||||
|
dup2(p_stdin[0], 0);
|
||||||
|
close(p_stdout[0]);
|
||||||
|
dup2(p_stdout[1], 1);
|
||||||
|
dup2(open("/dev/null", O_RDONLY), 2);
|
||||||
|
/// Close all other descriptors for the safety sake.
|
||||||
|
for (int i = 3; i < 4096; ++i)
|
||||||
|
close(i);
|
||||||
|
|
||||||
|
setsid();
|
||||||
|
execl("/bin/sh", "sh", "-c", command, NULL);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_ghdl(char *command, ...) {
|
||||||
|
FILE *proc;
|
||||||
|
char buf[1 K];
|
||||||
|
char cmd[1 K];
|
||||||
|
|
||||||
|
char *arr[5];
|
||||||
|
char *start;
|
||||||
|
char *ptr;
|
||||||
|
int arrc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, command);
|
||||||
|
vsprintf(cmd, command, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
debug("RUN_GHDL: %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"
|
||||||
|
// ../blink/src/abc.vhd:12:14:warning: package "mypack" does not require a body
|
||||||
|
// v
|
||||||
|
// ** Error: /tmp/filename.vhd(32): (vcom-1136) Unknown identifier "counter_i2".
|
||||||
|
|
||||||
|
while(42){
|
||||||
|
ptr = buf - 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ptr++;
|
||||||
|
*ptr = fgetc(proc);
|
||||||
|
} while (*ptr != '\0' && *ptr != '\n' && *ptr != -1 && ptr < buf + sizeof(buf));
|
||||||
|
if (*ptr == -1)
|
||||||
|
break;
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
ptr = buf;
|
||||||
|
start = buf;
|
||||||
|
arrc = 0;
|
||||||
|
|
||||||
|
//printf("** BUF: %s\n", buf);
|
||||||
|
do { // Split into params
|
||||||
|
if (*ptr == ' ') {
|
||||||
|
arr[arrc++] = start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (arrc < 5 && (*ptr == ':' || *ptr == '\0')) {
|
||||||
|
arr[arrc++] = start;
|
||||||
|
if (*ptr == '\0')
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
*ptr++ = 0;
|
||||||
|
start = ptr;
|
||||||
|
}
|
||||||
|
} while (*ptr++ != '\0');
|
||||||
|
|
||||||
|
if (arrc == 4) {
|
||||||
|
printf("** Error: %s(%s): (ghdl) %s\n", arr[0], arr[1], arr[3]);
|
||||||
|
}
|
||||||
|
else if (arrc == 5) {
|
||||||
|
printf("** Warning: %s(%s): (ghdl) %s\n", arr[0], arr[1], arr[4]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("** ghdl: ");
|
||||||
|
for (i = 0; i < arrc; i++) {
|
||||||
|
printf("%s", arr[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pclose(proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_simulation(char *command, ...) {
|
||||||
|
FILE *proc;
|
||||||
|
char buf[1 K];
|
||||||
|
char cmd[1 K];
|
||||||
|
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, command);
|
||||||
|
vsprintf(cmd, command, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
debug("RUN_SIM: %s\n", cmd);
|
||||||
|
proc = popen(cmd, "r");
|
||||||
|
|
||||||
|
if (proc == NULL) {
|
||||||
|
printf("[E] Could not start the simulation.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(fgets(buf, sizeof(buf), proc)!=NULL){
|
||||||
|
printf("** sim: %s", buf);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return pclose(proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_gtkwave(char *toplevel, char *command, ...) {
|
||||||
|
FILE *fp;
|
||||||
|
pid_t pid;
|
||||||
|
char cmd[1 K];
|
||||||
|
char lockpath[1 K];
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
sprintf(lockpath, "/tmp/model-ghdl-gtkw-%s.lock", toplevel);
|
||||||
|
|
||||||
|
fp = fopen(lockpath,"r");
|
||||||
|
if (fp) {
|
||||||
|
fgets(cmd, sizeof(cmd), fp); // lets (ab)use the cmd variable here
|
||||||
|
pid = atoi(cmd);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (kill(pid, 0)) { // Check if the process still lives
|
||||||
|
pid = -1;
|
||||||
|
}
|
||||||
|
/*else {
|
||||||
|
printf("GtkWave is already running.\n");
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pid = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid < 0) {
|
||||||
|
va_start(argptr, command);
|
||||||
|
vsprintf(cmd, command, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
debug("RUN_GTKWAVE: %s\n", cmd);
|
||||||
|
|
||||||
|
pid = system2(cmd, NULL, NULL);
|
||||||
|
//debug("--> PID=%d\n", pid);
|
||||||
|
|
||||||
|
// Prevent gtkw from starting again each time
|
||||||
|
fp = fopen(lockpath,"w");
|
||||||
|
if (fp) {
|
||||||
|
fprintf(fp, "%d", pid);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("[W] Could not create temp file %s! Ignoring...", lockpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int vsim(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *text = NULL;
|
||||||
|
char *work = NULL;
|
||||||
|
char *toplevel = NULL;
|
||||||
|
char *gtkwPrefix = NULL;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
char *ptr = NULL;
|
||||||
|
char *lastPtr;
|
||||||
|
char workdir[1 K];
|
||||||
|
char sourcedir[1 K];
|
||||||
|
char *params = NULL;
|
||||||
|
char *simtime = NULL;
|
||||||
|
char *simExt = NULL;
|
||||||
|
char *outFileType = NULL;
|
||||||
|
char vhdlver[16] = "";
|
||||||
|
int precompiled = 1;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
append_string(¶ms,"");
|
||||||
|
|
||||||
|
gui_init(&argc, &argv);
|
||||||
|
|
||||||
|
if (!getcwd(sourcedir, sizeof(sourcedir))) { // Default compile dir is cwd
|
||||||
|
sourcedir[0] = 0;
|
||||||
|
printf("[W] Could not get cwd!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen("/tmp/model-ghdl-vsim","r");
|
||||||
|
if (fp) {
|
||||||
|
fgets(workdir, sizeof(workdir), fp); // lets (ab)use the workdir variable here
|
||||||
|
append_string(&simtime, workdir);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
append_string(&simtime, "100ns");
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen("/tmp/model-ghdl-vcom","r");
|
||||||
|
if (fp) {
|
||||||
|
fgets(workdir, sizeof(workdir), fp); // (ab)use workdir variable as temp
|
||||||
|
if (!strcmp(workdir,"nopre\n"))
|
||||||
|
precompiled = 0;
|
||||||
|
fgets(workdir, sizeof(workdir), fp);
|
||||||
|
workdir[strlen(workdir)-1] = 0;
|
||||||
|
fgets(vhdlver, sizeof(vhdlver), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("[E] Could not read temp file /tmp/model-ghdl-vcom! Aborting...");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("[I] Emulating vsim.\n");
|
||||||
|
// -gui work.toplevel(RTL)
|
||||||
|
for (i=1; i < argc; ++i) {
|
||||||
|
if (ptr == NULL && GETOPT("-gui")) { // only allow once
|
||||||
|
append_string(&ptr, argv[i]);
|
||||||
|
lastPtr = ptr;
|
||||||
|
for (; *ptr != 0; ptr++) {
|
||||||
|
if (*ptr >= 'A' && *ptr <= 'Z')
|
||||||
|
*ptr = *ptr - ('A'-'a'); // convert to lower case
|
||||||
|
|
||||||
|
if (*ptr == '.') {
|
||||||
|
*ptr++ = 0;
|
||||||
|
work = lastPtr;
|
||||||
|
lastPtr = ptr;
|
||||||
|
}
|
||||||
|
else if (*ptr == '(') {
|
||||||
|
*ptr++ = 0;
|
||||||
|
toplevel = lastPtr;
|
||||||
|
lastPtr = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// free(ptr); DO NOT FREE, we still need it.
|
||||||
|
// ptr = NULL;
|
||||||
|
}
|
||||||
|
else if (GETOPT("-type")) {
|
||||||
|
append_string(&simExt, argv[i]);
|
||||||
|
}
|
||||||
|
else if (GETOPT("-ghdl")) {
|
||||||
|
append_string(¶ms, " ");
|
||||||
|
append_string(¶ms, argv[i]);
|
||||||
|
}
|
||||||
|
else if (GETOPT("-gtkwprefix")) {
|
||||||
|
gtkwPrefix = argv[i];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simExt == NULL)
|
||||||
|
append_string(&simExt, "ghw");
|
||||||
|
|
||||||
|
if (!strcmp(simExt,"ghw")) {
|
||||||
|
append_string(&outFileType, "wave");
|
||||||
|
}
|
||||||
|
else if (!strcmp(simExt,"vcd")) {
|
||||||
|
append_string(&outFileType, "vcd");
|
||||||
|
}
|
||||||
|
else if (!strcmp(simExt,"fst")) {
|
||||||
|
append_string(&outFileType, "fst");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "[E] Unknown output file type!");
|
||||||
|
showMessage(MESSAGE_ERROR, "Error! Unknown output file type.", NULL, NULL);
|
||||||
|
return 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir(workdir);
|
||||||
|
|
||||||
|
if (gtkwPrefix == NULL) {
|
||||||
|
append_string(>kwPrefix, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[I] Compiling...\n");
|
||||||
|
if (run_ghdl("ghdl -%c %s --work=%s --workdir=\"%s\" %s %s", (precompiled ? 'e' : 'm'), vhdlver, work, workdir, params, toplevel)) {
|
||||||
|
fprintf(stderr, "[E] Compilation failed!");
|
||||||
|
showMessage(MESSAGE_ERROR, "Error! Compilation failed.", NULL, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ret = showMessage(MESSAGE_INPUT, "Enter the simulation time: ", simtime, &text)) {
|
||||||
|
free(simtime);
|
||||||
|
simtime = NULL;
|
||||||
|
append_string(&simtime, text);
|
||||||
|
fp = fopen("/tmp/model-ghdl-vsim","w");
|
||||||
|
if (fp) {
|
||||||
|
fprintf(fp, "%s", simtime);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[I] Simulating...\n");
|
||||||
|
if (run_simulation("%s/%s --stop-time=%s --%s=%s.%s", workdir, toplevel, simtime, outFileType, toplevel, simExt)) {
|
||||||
|
fprintf(stderr, "[E] Simulation failed!");
|
||||||
|
showMessage(MESSAGE_ERROR, "Error! Simulation failed.", NULL, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (run_gtkwave(toplevel, "gtkwave %s/%s.%s --save=\"%s/%s%s.gtkw\"", workdir, toplevel, simExt, sourcedir, gtkwPrefix, toplevel)) {
|
||||||
|
fprintf(stderr, "[E] Could not open GtkWave!");
|
||||||
|
showMessage(MESSAGE_ERROR, "Error! Could not open GtkWave!", NULL, NULL);
|
||||||
|
}
|
||||||
|
printf("[I] DONE.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ptr); // Now we can free it
|
||||||
|
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vcom(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char workdir[1 K];
|
||||||
|
char *params = NULL;
|
||||||
|
char *work = NULL;
|
||||||
|
char *files = NULL;
|
||||||
|
char vhdlver[16] = "";
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int precompile = 1;
|
||||||
|
|
||||||
|
printf ("[I] Emulating vcom.\n");
|
||||||
|
|
||||||
|
if (!getcwd(workdir, sizeof(workdir))) { // Default compile dir is cwd
|
||||||
|
fprintf(stderr, "[E] Could not get cwd!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=1; i < argc; ++i) {
|
||||||
|
if (GETOPT("-work")) {
|
||||||
|
work = argv[i];
|
||||||
|
}
|
||||||
|
else if (GETOPT("-workdir")) {
|
||||||
|
strcpy(workdir, argv[i]);
|
||||||
|
}
|
||||||
|
else if (ISOPT("-87")) {
|
||||||
|
strcpy(vhdlver, "--std=87");
|
||||||
|
}
|
||||||
|
else if (ISOPT("-93")) {
|
||||||
|
strcpy(vhdlver, "--std=93");
|
||||||
|
}
|
||||||
|
else if (ISOPT("-93c")) {
|
||||||
|
strcpy(vhdlver, "--std=93c");
|
||||||
|
}
|
||||||
|
else if (ISOPT("-2000")) {
|
||||||
|
strcpy(vhdlver, "--std=00");
|
||||||
|
}
|
||||||
|
else if (ISOPT("-2002")) {
|
||||||
|
strcpy(vhdlver, "--std=02");
|
||||||
|
}
|
||||||
|
else if (ISOPT("-2008")) {
|
||||||
|
strcpy(vhdlver, "--std=08");
|
||||||
|
}
|
||||||
|
else if (ISOPT("-no-precompile")) {
|
||||||
|
precompile = 0;
|
||||||
|
}
|
||||||
|
else if (GETOPT("-ghdl")) {
|
||||||
|
append_string(¶ms, " ");
|
||||||
|
append_string(¶ms, argv[i]);
|
||||||
|
}
|
||||||
|
else if (argv[i][0] != '-'){ // VHDL file
|
||||||
|
append_string(&files, " ");
|
||||||
|
append_string(&files, argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!params)
|
||||||
|
append_string(¶ms, "");
|
||||||
|
if (!work)
|
||||||
|
append_string(&work, "work");
|
||||||
|
|
||||||
|
if (!files) {
|
||||||
|
fprintf(stderr, "[E] No input files specified.\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info for vsim later on
|
||||||
|
fp = fopen("/tmp/model-ghdl-vcom","w");
|
||||||
|
if (fp) {
|
||||||
|
fprintf(fp, "%s\n%s\n%s", (precompile ? "pre" : "nopre"), workdir, vhdlver);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("[W] Could not create temp file /tmp/model-ghdl-vcom! Ignoring...");
|
||||||
|
}
|
||||||
|
|
||||||
|
run_ghdl("ghdl -i --work=%s --workdir=%s %s %s %s 2>&1",
|
||||||
|
work, workdir, vhdlver, params, files);
|
||||||
|
run_ghdl("ghdl -%c --work=%s --workdir=%s %s %s %s 2>&1",
|
||||||
|
(precompile ? 'a' : 's'), work, workdir, vhdlver, params, files);
|
||||||
|
|
||||||
|
free(files);
|
||||||
|
|
||||||
|
printf("[I] DONE.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) + 1) * sizeof(char));
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(*dest, src);
|
||||||
|
return *dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
printf ("model-ghdl revision %s, compiled on %s.\n", PROGRAM_REVISION, __DATE__);
|
||||||
|
|
||||||
|
switch (get_application(argv[0])) {
|
||||||
|
case PROG_VCOM:
|
||||||
|
return vcom(argc, argv);
|
||||||
|
case PROG_VSIM:
|
||||||
|
return vsim(argc, argv);
|
||||||
|
case PROG_VMAP:
|
||||||
|
case PROG_VLIB:
|
||||||
|
case PROG_VDEL:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
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*) getAfter(call, "/");
|
||||||
|
if (strcmp(pos, "vcom") == 0) {
|
||||||
|
return PROG_VCOM;
|
||||||
|
}
|
||||||
|
else if (strcmp(pos, "vsim") == 0) {
|
||||||
|
return PROG_VSIM;
|
||||||
|
}
|
||||||
|
else if (strcmp(pos, "vlib") == 0) {
|
||||||
|
return PROG_VLIB;
|
||||||
|
}
|
||||||
|
else if (strcmp(pos, "vmap") == 0) {
|
||||||
|
return PROG_VMAP;
|
||||||
|
}
|
||||||
|
else if (strcmp(pos, "vdel") == 0) {
|
||||||
|
return PROG_VDEL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "[E] Program not recognized: %s\n", pos);
|
||||||
|
return PROG_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the string after the last occurence of __needle
|
||||||
|
const char *getAfter (const char *__haystack, const char *__needle) {
|
||||||
|
char *pos, *realPos;
|
||||||
|
char *haystack;
|
||||||
|
haystack = (char*) __haystack;
|
||||||
|
pos = (char*) __haystack;
|
||||||
|
while (pos != NULL) {
|
||||||
|
realPos = pos + 1;
|
||||||
|
pos = strstr(haystack, __needle);
|
||||||
|
if (haystack == __haystack && pos == NULL) // If no __needle is present at all...
|
||||||
|
realPos = (char*) __haystack; // Return the entire string
|
||||||
|
haystack = pos + 1;
|
||||||
|
}
|
||||||
|
return realPos;
|
||||||
|
}
|
||||||
190
vcom/main.cpp
190
vcom/main.cpp
@@ -1,190 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// #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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
TEMPLATE = app
|
|
||||||
CONFIG += console
|
|
||||||
CONFIG -= app_bundle
|
|
||||||
CONFIG -= qt
|
|
||||||
|
|
||||||
SOURCES += main.cpp
|
|
||||||
|
|
||||||
#QMAKE_CXXFLAGS += -std=c++11
|
|
||||||
238
vsim/main.cpp
238
vsim/main.cpp
@@ -1,238 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// #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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
TEMPLATE = app
|
|
||||||
CONFIG += console
|
|
||||||
CONFIG -= app_bundle
|
|
||||||
CONFIG -= qt
|
|
||||||
|
|
||||||
|
|
||||||
SOURCES += main.cpp
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user