Write package headers to a library file

Build up a work library by writing a VHDL representation of the
package header into a source file. This representation needs to
be accurate enough that later invocations of vhdlpp can read them
with the VHDL parser.
This commit is contained in:
Stephen Williams 2011-07-19 19:19:27 -07:00
parent 2cb9a2360c
commit 38854822da
10 changed files with 195 additions and 2 deletions

View File

@ -63,6 +63,7 @@ O = main.o architec.o compiler.o entity.o \
expression.o package.o scope.o sequential.o vsignal.o vtype.o \
architec_elaborate.o entity_elaborate.o expression_elaborate.o \
sequential_elaborate.o vtype_elaborate.o \
entity_stream.o vtype_stream.o \
lexor.o lexor_keyword.o parse.o \
parse_misc.o library.o vhdlreal.o vhdlint.o \
architec_emit.o entity_emit.o expression_emit.o sequential_emit.o vtype_emit.o \

View File

@ -30,4 +30,6 @@ extern StringHeapLex lex_strings;
extern StringHeapLex filename_strings;
extern void library_set_work_path(const char*work_path);
#endif

View File

@ -65,8 +65,11 @@ class ComponentBase : public LineInfo {
// empties the list in the process.
void set_interface(std::list<InterfacePort*>*ports);
void write_to_stream(std::ostream&fd) const;
public:
void dump_ports(ostream&out, int indent = 0) const;
void dump_ports(std::ostream&out, int indent = 0) const;
protected:
// This is really only used by the Entity derived class.

57
vhdlpp/entity_stream.cc Normal file
View File

@ -0,0 +1,57 @@
/*
* 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"
using namespace std;
void ComponentBase::write_to_stream(ostream&fd) const
{
fd << " component " << name_ << " is" << endl;
fd << " port(" << endl;
vector<InterfacePort*>::const_iterator cur = ports_.begin();
while (cur != ports_.end()) {
InterfacePort*item = *cur;
++cur;
fd << " " << item->name << " : ";
switch (item->mode) {
case PORT_NONE:
fd << "???? ";
break;
case PORT_IN:
fd << "in ";
break;
case PORT_OUT:
fd << "out ";
break;
}
item->type->write_to_stream(fd);
if (cur != ports_.end())
fd << ";" << endl;
else
fd << endl;
}
fd << " );" << endl;
fd << " end component;" << endl;
}

View File

@ -20,10 +20,16 @@
# include "parse_misc.h"
# include "compiler.h"
# include "package.h"
# include <fstream>
# include <map>
# include <string>
# include <cassert>
using namespace std;
static const char*library_work_path = 0;
static void store_package_in_work(const Package*pack);
struct library_contents {
map<perm_string,Package*> packages;
};
@ -69,6 +75,9 @@ void library_save_package(const char*libname, Package*pack)
struct library_contents&lib = libraries[use_libname];
lib.packages[pack->name()] = pack;
if (use_libname == "work")
store_package_in_work(pack);
}
void library_import(const YYLTYPE&loc, const std::list<perm_string>*names)
@ -211,3 +220,18 @@ void generate_global_types(ActiveScope*res)
res->bind_name(perm_string::literal("std_logic"), &primitive_STDLOGIC);
res->bind_name(perm_string::literal("bit_vector"),&primitive_BOOL_VECTOR);
}
void library_set_work_path(const char*path)
{
assert(library_work_path == 0);
library_work_path = path;
}
static void store_package_in_work(const Package*pack)
{
string path = string(library_work_path).append("/").append(pack->name()).append(".pkg");
ofstream file (path.c_str(), ios_base::out|ios_base::app);
pack->write_to_stream(file);
}

View File

@ -45,9 +45,11 @@ const char NOTICE[] =
# include <cstdio>
# include <cstdlib>
# include <cstring>
# include <cerrno>
#if defined(HAVE_GETOPT_H)
# include <getopt.h>
#endif
# include <sys/stat.h>
bool verbose_flag = false;
@ -55,6 +57,7 @@ bool verbose_flag = false;
const char*dump_design_entities_path = 0;
const char*dump_libraries_path = 0;
extern void dump_libraries(ostream&file);
static void process_debug_token(const char*word)
@ -74,8 +77,9 @@ int main(int argc, char*argv[])
{
int opt;
int rc;
const char*work_path = "ivl_vhdl_work";
while ( (opt=getopt(argc, argv, "D:vV")) != EOF) switch (opt) {
while ( (opt=getopt(argc, argv, "D:vVw:")) != EOF) switch (opt) {
case 'D':
process_debug_token(optarg);
@ -96,8 +100,27 @@ int main(int argc, char*argv[])
fputs(NOTICE, stdout);
break;
case 'w':
work_path = optarg;
break;
}
if ( (rc = mkdir(work_path, 0777)) < 0 ) {
if (errno != EEXIST) {
fprintf(stderr, "Icarus Verilog VHDL unable to create work directory %s, errno=%d\n", work_path, errno);
return -1;
}
struct stat stat_buf;
rc = stat(work_path, &stat_buf);
if (!S_ISDIR(stat_buf.st_mode)) {
fprintf(stderr, "Icarus Verilog VHDL work path `%s' is not a directory.\n", work_path);
return -1;
}
}
library_set_work_path(work_path);
preload_global_types();
int errors = 0;

View File

@ -18,6 +18,7 @@
*/
# include "package.h"
# include "entity.h"
Package::Package(perm_string n, const ScopeBase&ref)
: Scope(ref), name_(n)
@ -27,3 +28,16 @@ Package::Package(perm_string n, const ScopeBase&ref)
Package::~Package()
{
}
void Package::write_to_stream(ostream&fd) const
{
fd << "package " << name_ << " is" << endl;
for (map<perm_string,ComponentBase*>::const_iterator cur = components_.begin()
; cur != components_.end() ; ++cur) {
cur->second->write_to_stream(fd);
}
fd << "end package " << name_ << ";" << endl;
}

View File

@ -21,6 +21,7 @@
# include "scope.h"
# include "LineInfo.h"
# include <iostream>
class Package : public Scope, public LineInfo {
@ -30,6 +31,9 @@ class Package : public Scope, public LineInfo {
perm_string name() const { return name_; }
// This method writes a package header to a library file.
void write_to_stream(std::ostream&fd) const;
private:
perm_string name_;
};

View File

@ -36,6 +36,11 @@ class VType {
VType() { }
virtual ~VType() =0;
// This virtual method writes a VHDL-accurate representation
// of this type to the designated stream. This is used for
// writing parsed types to library files.
virtual void write_to_stream(std::ostream&fd) const;
virtual void show(std::ostream&) const;
public:
@ -74,6 +79,7 @@ class VTypePrimitive : public VType {
VTypePrimitive(type_t);
~VTypePrimitive();
void write_to_stream(std::ostream&fd) const;
void show(std::ostream&) const;
void elaborate(decl_t&decl) const;
@ -116,6 +122,7 @@ class VTypeArray : public VType {
VTypeArray(const VType*etype, const std::vector<range_t>&r, bool signed_vector =false);
~VTypeArray();
void write_to_stream(std::ostream&fd) const;
void show(std::ostream&) const;
void elaborate(decl_t&decl) const;

58
vhdlpp/vtype_stream.cc Normal file
View File

@ -0,0 +1,58 @@
/*
* 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 "vtype.h"
# include <typeinfo>
# include <cassert>
using namespace std;
void VType::write_to_stream(ostream&fd) const
{
fd << "/* UNKNOWN TYPE: " << typeid(*this).name() << " */";
}
void VTypeArray::write_to_stream(ostream&fd) const
{
fd << "array ";
if (ranges_.size() > 0) {
assert(ranges_.size() < 2);
fd << "(" << ranges_[0].msb()
<< " downto " << ranges_[0].lsb() << ") ";
}
fd << "of ";
etype_->write_to_stream(fd);
}
void VTypePrimitive::write_to_stream(ostream&fd) const
{
switch (type_) {
case INTEGER:
fd << "integer";
break;
case STDLOGIC:
fd << "std_logic";
break;
default:
assert(0);
fd << "/* PRIMITIVE: " << type_ << " */";
break;
}
}