Merge branch 'work3'

This commit is contained in:
Stephen Williams 2011-01-22 09:53:57 -08:00
commit 591c35cd7c
25 changed files with 1290 additions and 30 deletions

7
.gitignore vendored
View File

@ -43,6 +43,13 @@ dep
/ivlpp/lexor.c
/vhdlpp/lexor.cc
/vhdlpp/lexor_keyword.cc
/vhdlpp/parse.cc
/vhdlpp/parse.h
/vhdlpp/vhdlpp_config.h
/vhdlpp/vhdlpp
/lexor.cc
/lexor_keyword.cc
/parse.cc

View File

@ -38,7 +38,7 @@ exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
SUBDIRS = ivlpp vvp vpi libveriuser cadpli tgt-null tgt-stub tgt-vvp \
SUBDIRS = ivlpp vhdlpp vvp vpi libveriuser cadpli tgt-null tgt-stub tgt-vvp \
tgt-vhdl tgt-vlog95 driver
# Only run distclean for these directories.
NOTUSED = tgt-fpga tgt-pal tgt-verilog
@ -80,9 +80,9 @@ PS2PDF = @PS2PDF@
GIT = @GIT@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I.
INCLUDE_PATH = -I. -Ilibmisc
else
INCLUDE_PATH = -I. -I$(srcdir)
INCLUDE_PATH = -I. -Ilibmisc -I$(srcdir) -I$(srcdir)/libmisc
endif
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
@ -91,6 +91,9 @@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
# Source files in the libmisc directory
M = LineInfo.o StringHeap.o
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
@ -104,9 +107,9 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
pform_disciplines.o pform_dump.o pform_types.o set_width.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \
Attrib.o HName.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
Statement.o AStatement.o StringHeap.o $(FF) $(TT)
Statement.o AStatement.o $M $(FF) $(TT)
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
@ -197,7 +200,7 @@ ifeq (@WIN32@,yes)
# The first step makes an ivl.exe that dlltool can use to make an
# export and import library, and the last link makes a, ivl.exe
# that really exports the things that the import library imports.
ivl@EXEEXT@: $O $(srcdir)/ivl.def
ivl@EXEEXT@: $O $(srcdir)/ivl.def
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
dlltool --dllname ivl@EXEEXT@ --def $(srcdir)/ivl.def \
--output-lib libivl.a --output-exp ivl.exp
@ -229,6 +232,10 @@ version.exe: $(srcdir)/version.c $(srcdir)/version_base.h version_tag.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep/$*.d
%.o: $(srcdir)/libmisc/%.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep/$*.d
# Here are some explicit dependencies needed to get things going.
main.o: main.cc version_tag.h

View File

@ -2,6 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(netlist.h)
AC_CONFIG_HEADER(config.h)
AC_CONFIG_HEADER(_pli_types.h)
AC_CONFIG_HEADER(vhdlpp/vhdlpp_config.h)
AC_CONFIG_HEADER(vvp/config.h)
AC_CONFIG_HEADER(vpi/vpi_config.h)
AC_CONFIG_HEADER(libveriuser/config.h)
@ -295,4 +296,4 @@ AC_MSG_RESULT(ok)
# XXX disable tgt-fpga for the moment
AC_OUTPUT(Makefile ivlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile)
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile)

View File

@ -106,7 +106,8 @@ const char sep = '/';
extern void cfreset(FILE*fd, const char*path);
const char*base = 0;
const char*pbase = 0;
const char*ivlpp_dir = 0;
const char*vhdlpp_dir= 0;
const char*mtm = 0;
const char*opath = "a.out";
const char*npath = 0;
@ -304,7 +305,7 @@ static int t_version_only(void)
free(source_path);
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
snprintf(tmp, sizeof tmp, "%s%civlpp -V", ivlpp_dir, sep);
rc = system(tmp);
if (rc != 0) {
fprintf(stderr, "Unable to get version from \"%s\"\n", tmp);
@ -333,7 +334,7 @@ static int t_version_only(void)
static void build_preprocess_command(int e_flag)
{
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F\"%s\" -f\"%s\" -p\"%s\" ",
pbase, sep, verbose_flag?" -v":"",
ivlpp_dir, sep, verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
}
@ -875,14 +876,20 @@ int main(int argc, char **argv)
switch (opt) {
case 'B':
/* Undocumented feature: The preprocessor itself
may be located at a different location. If the
base starts with a 'P', set this special base
instead of the main base. */
if (optarg[0] == 'P') {
pbase = optarg+1;
} else {
/* The individual components can be located by a
single base, or by individual bases. The first
character of the path indicates which path the
user is specifying. */
switch (optarg[0]) {
case 'P': /* Path for the ivlpp preprocessor */
ivlpp_dir = optarg+1;
break;
case 'V': /* Path for the vhdlpp VHDL processor */
vhdlpp_dir = optarg+1;
break;
default: /* Otherwise, this is a default base. */
base=optarg;
break;
}
break;
case 'c':
@ -995,8 +1002,10 @@ int main(int argc, char **argv)
}
}
if (pbase == 0)
pbase = base;
if (ivlpp_dir == 0)
ivlpp_dir = base;
if (vhdlpp_dir == 0)
vhdlpp_dir = base;
if (version_flag || verbose_flag) {
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
@ -1017,6 +1026,8 @@ int main(int argc, char **argv)
snprintf(iconfig_common_path, sizeof iconfig_common_path, "%s%c%s%s.conf",
base, sep, targ, synth_flag? "-s" : "");
fprintf(defines_file, "vhdlpp:%s%cvhdlpp\n", vhdlpp_dir, sep);
/* Write values to the iconfig file. */
fprintf(iconfig_file, "basedir:%s\n", base);
@ -1143,7 +1154,7 @@ int main(int argc, char **argv)
single file. This may be used to preprocess library
files. */
fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F\"%s\" -P\"%s\"\n",
pbase, sep, defines_path, compiled_defines_path);
ivlpp_dir, sep, defines_path, compiled_defines_path);
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);

View File

@ -33,6 +33,8 @@ extern void dump_precompiled_defines(FILE*out);
an include directive in encountered. */
extern char**include_dir;
extern unsigned include_cnt;
/* Program to use for VHDL processing. */
extern char*vhdlpp_path;
extern int relative_include;

View File

@ -42,6 +42,15 @@ valid options include:
This option does *not* override existing `define
directives in the source file.
-F <path>
Read ivlpp options from a FLAGS FILE. This is not the same
as a file list. This file contains flags, not source
files. There may be multiple flags files.
-f <path>
Read ivlpp input files from a file list. There can be no
more then one file list.
-I <dir>
Add a directory to the include path. Normally, only "." is
in the search path. The -I flag causes other directories
@ -59,8 +68,42 @@ valid options include:
output.
-v
Print version and copyright information
Print version and copyright information before processing
input files.
-V
Print version and copyright information, then exit WITHOUT
processing any input files.
FLAGS FILE
A flags file contains flags for use by ivlpp. This is a convenient way
for programs to pass complex sets of flags to the ivlpp program.
Blank lines and lines that start with "#" are ignored. The latter can
be used as comment lines. All other lines are flag lines. Leading and
trailing white space are removed before the lines are interpreted.
Other lines have the simple format:
<key>:<value>
The colon character separates a key from the value. The supported
keys, with their corresponding values, are:
D:name=<value>
This is exactly the same as the "-Dname=<value>" described above.
I:<dir>
This is exctly the same as "-I<dir>".
relative include:<flag>
The <flag> can be "true" or "false". This enables "relative
includes" nesting behavior.
vhdlpp:<path>
Give the path to the vhdlpp program. This program is used to
process VHDL input files.
LOCATING INCLUDED FILES

View File

@ -59,6 +59,7 @@ struct include_stack_t
/* If the current input is from a file, this member is set. */
FILE* file;
int (*file_close)(FILE*);
/* If we are reparsing a macro expansion, file is 0 and this
* member points to the string in progress
@ -1614,8 +1615,10 @@ static void do_include()
{
/* standby is defined by include_filename() */
if (standby->path[0] == '/') {
if ((standby->file = fopen(standby->path, "r")))
if ((standby->file = fopen(standby->path, "r"))) {
standby->file_close = fclose;
goto code_that_switches_buffers;
}
} else {
unsigned idx, start = 1;
char path[4096];
@ -1644,6 +1647,7 @@ static void do_include()
sprintf(path, "%s/%s", include_dir[idx], standby->path);
if ((standby->file = fopen(path, "r"))) {
standby->file_close = fclose;
/* Free the original path before we overwrite it. */
free(standby->path);
standby->path = strdup(path);
@ -1750,6 +1754,58 @@ static void lexor_done()
}
}
/*
* Use this function to open a source file that is to be
* processed. Do NOT use this function for opening include files,
* instead only use this file for opening base source files.
*/
static void open_input_file(struct include_stack_t*isp)
{
char*cp;
int is_vhdl = 0;
isp->file = 0;
/* look for a suffix for the input file. If the suffix
indicates that this is a VHDL source file, then invoke
vhdlpp to get a data stream. */
cp = strrchr(isp->path, '.');
if (cp && vhdlpp_path) {
if (strcmp(cp, ".vhd") == 0) {
is_vhdl = 1;
} else if (strcmp(cp, ".vhdl") == 0) {
is_vhdl = 1;
}
}
if (is_vhdl == 0) {
isp->file = fopen(isp->path, "r");
isp->file_close = fclose;
return;
}
size_t cmdlen = strlen(vhdlpp_path);
cmdlen += strlen(isp->path);
cmdlen += 32;
char*cmd = malloc(cmdlen);
snprintf(cmd, cmdlen, "%s %s", vhdlpp_path, isp->path);
isp->file = popen(cmd, "r");
isp->file_close = pclose;
free(cmd);
return;
}
/*
* The load_next_input() function is called by the lexical analyzer
* when the current file runs out. When the EOF of the current input
* file is matched, this function figures out if this is the end of an
* included file (in which case the including file is resumed) or the
* end of a base file, in which case the next base source file is
* opened.
*/
static int load_next_input()
{
int line_mask_flag = 0;
@ -1773,7 +1829,8 @@ static int load_next_input()
if (isp->file)
{
free(isp->path);
fclose(isp->file);
assert(isp->file_close);
isp->file_close(isp->file);
}
else
{
@ -1813,7 +1870,7 @@ static int load_next_input()
istack->next = 0;
istack->lineno = 0;
istack->file = fopen(istack->path, "r");
open_input_file(istack);
if (istack->file == 0)
{
@ -1966,7 +2023,7 @@ void reset_lexor(FILE* out, char* paths[])
isp = malloc(sizeof(struct include_stack_t));
isp->next = 0;
isp->path = strdup(paths[0]);
isp->file = fopen(paths[0], "r");
open_input_file(isp);
isp->str = 0;
isp->lineno = 0;
isp->stringify_flag = 0;

View File

@ -57,7 +57,8 @@ extern const char*optarg;
char *dep_path = NULL;
/* Dependency file output mode */
char dep_mode = 'a';
/* Path to vhdlpp */
char *vhdlpp_path = 0;
/*
* Keep in source_list an array of pointers to file names. The array
@ -166,6 +167,13 @@ static int flist_read_flags(const char*path)
relative_include = 0;
}
} else if (strcmp(cp,"vhdlpp") == 0) {
if (vhdlpp_path) {
fprintf(stderr, "Ignore multiple vhdlpp flags\n");
} else {
vhdlpp_path = strdup(arg);
}
} else {
fprintf(stderr, "%s: Invalid keyword %s\n", path, cp);
}

View File

@ -17,11 +17,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "LineInfo.h"
# include <sstream>
using namespace std;
LineInfo::LineInfo()
: lineno_(0)
{

View File

@ -21,7 +21,6 @@
# include <cstdlib>
# include <cstring>
# include <cassert>
# include "ivl_alloc.h"
#ifdef CHECK_WITH_VALGRIND
static char **string_pool = NULL;

View File

@ -19,7 +19,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include <string>
using namespace std;

118
vhdlpp/Makefile.in Normal file
View File

@ -0,0 +1,118 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
CC = @CC@
CXX = @CXX@
INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
YACC = @YACC@
ifeq (.,.)
INCLUDE_PATH = -I. -I.. -I../libmisc
else
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/../libmisc
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ @EXTRALIBS@
M = StringHeap.o LineInfo.o
O = main.o compiler.o entity.o entity_elaborate.o \
lexor.o lexor_keyword.o parse.o $M
all: dep vhdlpp@EXEEXT@
clean:
rm -f *.o *~
rm -rf dep vhdlpp@EXEEXT@
distclean: clean
rm -f Makefile config.log
rm -f stamp-vhdlpp_config-h vhdlpp_config.h
Makefile: $(srcdir)/Makefile.in
cd ..; ./config.status --file=vhdlpp/$@
dep:
mkdir dep
vhdlpp@EXEEXT@: $O
$(CXX) -o vhdlpp@EXEEXT@ $(LDFLAGS) $O $(LIBS)
%.o: $(srcdir)/../libmisc/%.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
%.o: %.cc vhdlpp_config.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep/$*.d
lexor.o: lexor.cc parse.h
parse.o: parse.cc
lexor.cc: $(srcdir)/lexor.lex
$(LEX) -s -olexor.cc $(srcdir)/lexor.lex
parse.cc parse.h: $(srcdir)/parse.y
$(YACC) --verbose -t -d -o parse.cc $(srcdir)/parse.y
mv parse.cc.h parse.h 2>/dev/null || mv parse.hh parse.h
lexor_keyword.o: lexor_keyword.cc parse.h
lexor_keyword.cc: $(srcdir)/lexor_keyword.gperf
gperf -o -i 7 --ignore-case -C -k 1-4,6,9,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
install: all installdirs $(libdir)/ivl$(suffix)/vhdlpp@EXEEXT@
$(libdir)/ivl$(suffix)/vhdlpp@EXEEXT@: vhdlpp@EXEEXT@
$(INSTALL_PROGRAM) ./vhdlpp@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/vhdlpp@EXEEXT@"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(libdir)/ivl$(suffix)"
uninstall:
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/ivhdlpp@EXEEXT@"
stamp-vhdlpp_config-h: $(srcdir)/vhdlpp_config.h.in ../config.status
@rm -f $@
cd ..; ./config.status --header=vhdlpp/vhdlpp_config.h
vhplpp_config.h: stamp-vhdlpp_config-h
-include $(patsubst %.o, dep/%.d, $O)

23
vhdlpp/compiler.cc Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "compiler.h"
StringHeapLex lex_strings;
StringHeapLex filename_strings;

33
vhdlpp/compiler.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef __compiler_H
#define __compiler_H
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "StringHeap.h"
const int GN_KEYWORD_2008 = 0x0001;
// TRUE if processing is supposed to dump progress to stderr.
extern bool verbose_flag;
extern StringHeapLex lex_strings;
extern StringHeapLex filename_strings;
#endif

73
vhdlpp/entity.cc Normal file
View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "entity.h"
# include <fstream>
# include <iomanip>
using namespace std;
std::map<perm_string,Entity*> design_entities;
static ostream& operator << (ostream&out, port_mode_t that)
{
switch (that) {
case PORT_NONE:
out << "NO-PORT";
break;
case PORT_IN:
out << "IN";
break;
case PORT_OUT:
out << "OUT";
break;
default:
out << "PORT-????";
break;
}
return out;
}
static void dump_design_entity(ostream&out, Entity*obj)
{
out << "entity " << obj->name << " file=" << obj->get_fileline() << endl;
if (obj->ports.size() == 0) {
out << " No ports" << endl;
} else {
out << " PORTS:" << endl;
for (vector<InterfacePort*>::iterator cur = obj->ports.begin()
; cur != obj->ports.end() ; ++cur) {
InterfacePort*item = *cur;
out << setw(6) << "" << item->name
<< " : " << item->mode
<< ", type=" << item->type_name
<< ", file=" << item->get_fileline() << endl;
}
}
}
void dump_design_entities(const char*path)
{
ofstream file (path);
for (map<perm_string,Entity*>::iterator cur = design_entities.begin()
; cur != design_entities.end() ; ++cur) {
dump_design_entity(file, cur->second);
}
}

68
vhdlpp/entity.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef __entity_H
#define __entity_H
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <map>
# include <vector>
# include "StringHeap.h"
# include "LineInfo.h"
typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t;
class InterfacePort : public LineInfo {
public:
// Port direction from the source code.
port_mode_t mode;
// Name of the port from the source code
perm_string name;
// Name of interface type as given in the source code.
perm_string type_name;
};
class Entity : public LineInfo {
public:
int elaborate();
public:
perm_string name;
std::vector<InterfacePort*> ports;
};
/*
* As the parser parses entities, it puts them into this map. It uses
* a map because sometimes it needs to look back at an entity by name.
*/
extern std::map<perm_string,Entity*> design_entities;
/*
* Elaborate the collected entities, and return the number of
* elaboration errors.
*/
extern int elaborate_entities(void);
/*
* Use this function to dump a description of the design entities to a
* file. This is for debug, not for any useful purpose.
*/
extern void dump_design_entities(const char*path);
#endif

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "entity.h"
# include "compiler.h"
# include <iostream>
# include <fstream>
# include <iomanip>
using namespace std;
int elaborate_entities(void)
{
int errors = 0;
for (map<perm_string,Entity*>::iterator cur = design_entities.begin()
; cur != design_entities.end() ; ++cur) {
errors += cur->second->elaborate();
}
return errors;
}
int Entity::elaborate()
{
int errors = 0;
if (verbose_flag)
cerr << "Elaborate entity " << name << "..." << endl;
cout << "module " << name;
// If there are ports, emit them.
if (ports.size() > 0) {
cout << "(";
const char*sep = 0;
for (vector<InterfacePort*>::iterator cur = ports.begin()
; cur != ports.end() ; ++cur) {
InterfacePort*port = *cur;
// FIXME: this is a stub. This port handling code
// currently only supports std_logic signal tyes,
// so just assert that the user asked for std_logic.
if (port->type_name != "std_logic") {
cerr << "sorry: VHDL only supports std_logic ports."
<< " Expecting std_logic, but got \""
<< port->type_name << "\"" << endl;
errors += 1;
}
if (sep) cout << sep;
else sep = ", ";
switch (port->mode) {
case PORT_NONE: // Should not happen
cout << "NO_PORT " << port->name;
break;
case PORT_IN:
cout << "input " << port->name;
break;
case PORT_OUT:
cout << "output " << port->name;
break;
}
}
cout << ")";
}
cout << ";" << endl;
cout << "endmodule" << endl;
return errors;
}

106
vhdlpp/lexor.lex Normal file
View File

@ -0,0 +1,106 @@
%option never-interactive
%option nounput
%option noyywrap
%{
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "parse_api.h"
# include "lexor_keyword.h"
# include "parse_wrap.h"
extern int lexor_keyword_code (const char*str, unsigned len);
/*
* Lexical location information is passed in the yylloc variable to th
* parser. The file names, strings, are kept in a list so that I can
* re-use them. The set_file_name function will return a pointer to
* the name as it exists in the list (and delete the passed string.)
* If the name is new, it will be added to the list.
*/
extern YYLTYPE yylloc;
static char* strdupnew(char const *str)
{
return str ? strcpy(new char [strlen(str)+1], str) : 0;
}
static int comment_enter;
%}
%x CCOMMENT
%x LCOMMENT
W [ \t\b\f\r]+
%%
[ \t\b\f\r] { ; }
\n { yylloc.first_line += 1; }
/* Single-line comments start with - - and run to the end of the
current line. These are very easy to handle. */
"--".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
<LCOMMENT>. { yymore(); }
<LCOMMENT>\n { yylloc.first_line += 1; BEGIN(comment_enter); }
/* The contents of C-style comments are ignored, like white space. */
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
<CCOMMENT>. { ; }
<CCOMMENT>\n { yylloc.first_line += 1; }
<CCOMMENT>"*/" { BEGIN(comment_enter); }
[a-zA-Z_][a-zA-Z0-9_]* {
int rc = lexor_keyword_code(yytext, yyleng);
switch (rc) {
case IDENTIFIER:
yylval.text = strdupnew(yytext);
break;
default:
break;
}
return rc;
}
/* Compound symbols */
"<=" { return LEQ; }
">=" { return GEQ; }
":=" { return VASSIGN; }
. { return yytext[0]; }
%%
extern void yyparse_set_filepath(const char*path);
void reset_lexor(FILE*fd, const char*path)
{
yylloc.text = path;
yylloc.first_line = 1;
yyrestart(fd);
yyparse_set_filepath(path);
}

View File

@ -0,0 +1,47 @@
/*
* We need this to prevent -Wextra (-W) from complaining that the mask and
* tokenType values are not initialized for the empty table entries.
*/
%define initializer-suffix ,0,0
%{
/* Command-line: gperf -o -i 1 --ignore-case -C -k 1-3,$ -L C -H keyword_hash -N check_identifier -tT lexor_keyword.gperf */
#include "vhdlpp_config.h"
#include <cstring>
#include "compiler.h"
#include "parse_api.h"
#include "parse_wrap.h"
%}
struct lexor_keyword { const char*name; int mask; int tokenType; };
%%
abs, GN_KEYWORD_2008, K_abs
access, GN_KEYWORD_2008, K_access
all, GN_KEYWORD_2008, K_all
and, GN_KEYWORD_2008, K_and
architecture, GN_KEYWORD_2008, K_architecture
begin, GN_KEYWORD_2008, K_begin
end, GN_KEYWORD_2008, K_end
entity, GN_KEYWORD_2008, K_entity
in, GN_KEYWORD_2008, K_in
is, GN_KEYWORD_2008, K_is
library, GN_KEYWORD_2008, K_library
of, GN_KEYWORD_2008, K_of
out, GN_KEYWORD_2008, K_out
port, GN_KEYWORD_2008, K_port
use, GN_KEYWORD_2008, K_use
%%
int lexor_keyword_mask = GN_KEYWORD_2008;
int lexor_keyword_code(const char*str, unsigned nstr)
{
const struct lexor_keyword*rc = check_identifier(str, nstr);
if (rc == 0)
return IDENTIFIER;
else if ((rc->mask & lexor_keyword_mask) == 0)
return IDENTIFIER;
else
return rc->tokenType;
}

127
vhdlpp/main.cc Normal file
View File

@ -0,0 +1,127 @@
const char COPYRIGHT[] =
"Copyright (c) 2011 Stephen Williams (steve@icarus.com)";
/*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "vhdlpp_config.h"
# include "version_base.h"
# include "version_tag.h"
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
" it under the terms of the GNU General Public License as published by\n"
" the Free Software Foundation; either version 2 of the License, or\n"
" (at your option) any later version.\n"
"\n"
" This program is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License along\n"
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
;
# include "compiler.h"
# include "parse_api.h"
# include <cstdio>
# include <cstdlib>
# include <cstring>
#if defined(HAVE_GETOPT_H)
# include <getopt.h>
#endif
bool verbose_flag = false;
// Where to dump design entities
const char*dump_design_entities_path = 0;
static void process_debug_token(const char*word)
{
if (strcmp(word, "yydebug") == 0) {
yydebug = 1;
} else if (strcmp(word, "no-yydebug") == 0) {
yydebug = 0;
} else if (strncmp(word, "entities=", 9) == 0) {
dump_design_entities_path = strdup(word+9);
}
}
int main(int argc, char*argv[])
{
int opt;
int rc;
while ( (opt=getopt(argc, argv, "D:vV")) != EOF) switch (opt) {
case 'D':
process_debug_token(optarg);
break;
case 'v':
fprintf(stderr, "Icarus Verilog VHDL Parse version "
VERSION " (" VERSION_TAG ")\n\n");
fprintf(stderr, "%s\n\n", COPYRIGHT);
fputs(NOTICE, stderr);
verbose_flag = true;
break;
case 'V':
fprintf(stdout, "Icarus Verilog VHDL Parse version "
VERSION " (" VERSION_TAG ")\n\n");
fprintf(stdout, "%s\n\n", COPYRIGHT);
fputs(NOTICE, stdout);
break;
}
for (int idx = optind ; idx < argc ; idx += 1) {
parse_errors = 0;
FILE*fd = fopen(argv[idx], "r");
if (fd == 0) {
perror(argv[idx]);
return 1;
}
reset_lexor(fd, argv[idx]);
rc = yyparse();
if (verbose_flag)
fprintf(stderr, "yyparse() returns %d, parse_errors=%d\n", rc, parse_errors);
if (parse_errors > 0) {
fprintf(stderr, "%d errors parsing %s\n", parse_errors, argv[idx]);
return 2;
}
fclose(fd);
}
if (dump_design_entities_path)
dump_design_entities(dump_design_entities_path);
int elaborate_errors = 0;
elaborate_errors = elaborate_entities();
if (elaborate_errors > 0) {
fprintf(stderr, "%d errors elaborating design.\n", elaborate_errors);
return 3;
}
lex_strings.cleanup();
return 0;
}

309
vhdlpp/parse.y Normal file
View File

@ -0,0 +1,309 @@
%{
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "vhdlpp_config.h"
# include "compiler.h"
# include "parse_api.h"
# include <cstdarg>
# include <list>
inline void FILE_NAME(LineInfo*tmp, const struct yyltype&where)
{
tmp->set_lineno(where.first_line);
tmp->set_file(filename_strings.make(where.text));
}
static void yyerror(const char*msg);
static void errormsg(const YYLTYPE&loc, const char*msg, ...);
int parse_errors = 0;
%}
%union {
port_mode_t port_mode;
char*text;
InterfacePort*interface_element;
std::list<InterfacePort*>* interface_list;
};
/* The keywords are all tokens. */
%token K_abs K_access K_after K_alias K_all K_and K_architecture
%token K_array K_assert K_assume K_assume_guarantee K_attribute
%token K_begin K_block K_body K_buffer K_bus
%token K_case K_component K_configuration K_constant K_context K_cover
%token K_default K_disconect K_downto
%token K_else K_elsif K_end K_entity K_exit
%token K_fairness K_file K_for K_force K_function
%token K_generate K_generic K_group K_guarded
%token K_if K_impure K_in K_internal K_inout K_is
%token K_label K_library K_linkage K_literal K_loop
%token K_map K_mod
%token K_nand K_new K_next K_nor K_not K_null
%token K_of K_on K_open K_or K_others K_out
%token K_package K_parameter K_port K_postponed K_procedure K_process
%token K_property K_protected K_pure
%token K_range K_record K_register K_reject K_release K_rem K_report
%token K_restrict K_restrict_guarantee K_return K_rol K_ror
%token K_select K_sequence K_seerity K_signal K_shared
%token K_sla K_sll K_sra K_srl K_string K_subtype
%token K_then K_to K_transport K_type
%token K_unaffected K_units K_until K_use
%token K_variable K_vmode K_vprop K_vunit
%token K_wait K_when K_while K_with
%token K_xnor K_xor
/* Identifiers that are not keywords are identifiers. */
%token <text> IDENTIFIER
/* compound symbols */
%token LEQ GEQ VASSIGN
/* The rules may have types. */
%type <interface_element> interface_element
%type <interface_list> interface_list entity_header port_clause
%type <port_mode> mode
%%
/* The design_file is the root for the VHDL parse. */
design_file : design_units ;
architecture_body
: K_architecture IDENTIFIER
K_of IDENTIFIER
K_is
K_begin architecture_statement_part K_end K_architecture_opt ';'
| K_architecture IDENTIFIER
K_of IDENTIFIER
K_is
K_begin error K_end K_architecture_opt ';'
{ errormsg(@1, "Syntax error in architecture statement.\n"); yyerrok; }
| K_architecture error ';'
{ errormsg(@1, "Syntax error in architecture body.\n"); yyerrok; }
;
/* The architecture_statement_part is a list of concurrent
statements. */
architecture_statement_part
: architecture_statement_part concurrent_statement
| concurrent_statement
;
concurrent_signal_assignment_statement
: IDENTIFIER LEQ waveform ';'
;
concurrent_statement
: concurrent_signal_assignment_statement
;
context_clause : context_items | ;
context_item
: library_clause
| use_clause
;
context_items
: context_items context_item
| context_item
;
design_unit
: context_clause library_unit
| error { errormsg(@1, "Invalid design_unit\n"); }
;
design_units
: design_units design_unit
| design_unit
;
/* As an entity is declared, add it to the map of design entities. */
entity_declaration
: K_entity IDENTIFIER K_is entity_header K_end K_entity ';'
{ Entity*tmp = new Entity;
FILE_NAME(tmp, @1);
// Store the name
tmp->name = lex_strings.make($2);
delete[]$2;
// Transfer the ports
std::list<InterfacePort*>*ports = $4;
while (ports->size() > 0) {
tmp->ports.push_back(ports->front());
ports->pop_front();
}
delete ports;
// Save the entity in the entity map.
design_entities[tmp->name] = tmp;
}
;
entity_header
: port_clause
{ $$ = $1; }
;
expression
: expression_logical
;
expression_logical
: relation K_and relation
| relation K_or relation
;
factor : primary ;
/* The interface_element is also an interface_declaration */
interface_element
: IDENTIFIER ':' mode IDENTIFIER
{ InterfacePort*tmp = new InterfacePort;
FILE_NAME(tmp, @1);
tmp->mode = $3;
tmp->name = lex_strings.make($1);
tmp->type_name = lex_strings.make($4);
delete[]$1;
delete[]$4;
$$ = tmp;
}
;
interface_list
: interface_list ';' interface_element
{ std::list<InterfacePort*>*tmp = $1;
tmp->push_back($3);
$$ = tmp;
}
| interface_element
{ std::list<InterfacePort*>*tmp = new std::list<InterfacePort*>;
tmp->push_back($1);
$$ = tmp;
}
;
library_clause
: K_library logical_name_list ';'
| K_library error ';'
{ errormsg(@1, "Syntax error in library clause.\n"); yyerrok; }
;
/* Collapse the primary_unit and secondary_unit of the library_unit
into this single set of rules. */
library_unit
: entity_declaration
| architecture_body
;
logical_name : IDENTIFIER ;
logical_name_list
: logical_name_list ',' logical_name
| logical_name
;
mode
: K_in { $$ = PORT_IN; }
| K_out { $$ = PORT_OUT; }
;
port_clause
: K_port '(' interface_list ')' ';'
{ $$ = $3; }
;
primary
: IDENTIFIER
;
relation : shift_expression ;
selected_name
: IDENTIFIER '.' K_all
| IDENTIFIER '.' IDENTIFIER '.' K_all
;
selected_names
: selected_names ',' selected_name
| selected_name
;
shift_expression : simple_expression ;
simple_expression : term ;
term : factor ;
use_clause
: K_use selected_names ';'
| K_use error ';'
{ errormsg(@1, "Syntax error in use clause.\n"); yyerrok; }
;
waveform
: waveform_elements
| K_unaffected
;
waveform_elements
: waveform_elements ',' waveform_element
| waveform_element
;
waveform_element
: expression
| K_null
;
/* Some keywords are optional in some contexts. In all such cases, a
similar rule is used, as described here. */
K_architecture_opt : K_architecture | ;
%%
static void yyerror(const char*msg)
{
fprintf(stderr, "%s\n", msg);
parse_errors += 1;
}
static const char*file_path = "";
static void errormsg(const YYLTYPE&loc, const char*fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s:%d: ", file_path, loc.first_line);
vfprintf(stderr, fmt, ap);
va_end(ap);
parse_errors += 1;
}
/*
* This is used only by the lexor, to set the file path used in error
* messages.
*/
void yyparse_set_filepath(const char*path)
{
file_path = path;
}

61
vhdlpp/parse_api.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef __parse_api_H
#define __parse_api_H
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <cstdio>
# include "entity.h"
/*
* The vlltype supports the passing of detailed source file location
* information between the lexical analyzer and the parser. Defining
* YYLTYPE compels the lexor to use this type and not something other.
*/
struct yyltype {
unsigned first_line;
unsigned first_column;
unsigned last_line;
unsigned last_column;
const char*text;
};
# define YYLTYPE struct yyltype
/*
* The reset_lexor function takes the fd and makes it the input file
* for the lexor. The path argument is used in lexor/parser error messages.
*/
extern void reset_lexor(FILE*fd, const char*path);
extern int yylex(void);
extern int yyparse(void);
/*
* Set this to a non-zero value to enable parser debug output.
*/
extern int yydebug;
/*
* The parser counts the errors that is handed in the parse_errors
* variable. For a clean compile, this value should not change. (The
* caller sets its initial value.)
*/
extern int parse_errors;
#endif

31
vhdlpp/parse_wrap.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef __parse_wrap_H
#define __parse_wrap_H
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/*
* This header wraps the parse.h header file that is generated from
* the parse.y source file. This is used to include definitions that
* are needed by the parse type, etc.
*/
# include <list>
# include "parse.h"
#endif

40
vhdlpp/vhdlpp_config.h.in Normal file
View File

@ -0,0 +1,40 @@
#ifndef __vhdlpp_config_H /* -*- c++ -*- */
#define __vhdlpp_config_H
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if defined(__cplusplus)
# if !defined(__GNUC__)
using namespace std;
# elif (__GNUC__ == 3)
using namespace std;
# endif
#endif
# undef HAVE_GETOPT_H
# undef HAVE_INTTYPES_H
# undef HAVE_LIBIBERTY_H
# undef HAVE_FCHMOD
# undef HAVE_SYS_WAIT_H
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#endif /* __config_H */