Add packages and component declarations within those packages.

This creates the Package class to represent packages, and the
Scope class to represent scopes in general. The library functions
are worked up to support scanning scopes for declarations that are
imported by "use" clauses.
This commit is contained in:
Stephen Williams 2011-04-13 18:30:00 -07:00
parent 791adfab68
commit d4c5cfc584
12 changed files with 323 additions and 63 deletions

View File

@ -60,9 +60,9 @@ LIBS = @LIBS@ @EXTRALIBS@
M = StringHeap.o LineInfo.o
O = main.o architec.o architec_elaborate.o compiler.o entity.o entity_elaborate.o \
expression.o vsignal.o vtype.o vtype_elaborate.o \
expression.o package.o scope.o vsignal.o vtype.o vtype_elaborate.o \
lexor.o lexor_keyword.o parse.o \
parse_misc.o vhdlreal.o vhdlint.o debug.o \
parse_misc.o library.o vhdlreal.o vhdlint.o debug.o \
architec_emit.o entity_emit.o expression_emit.o vtype_emit.o \
$M

View File

@ -26,10 +26,9 @@ using namespace std;
Architecture::Architecture(perm_string name, map<perm_string,Signal*>&sigs,
map<perm_string,ComponentBase*>&comps,
list<Architecture::Statement*>&s)
: name_(name)
: Scope(comps), name_(name)
{
signals_ = sigs;
components_ = comps;
statements_.splice(statements_.end(), s);
}
@ -37,15 +36,6 @@ Architecture::~Architecture()
{
}
const ComponentBase* Architecture::find_component(perm_string by_name)
{
map<perm_string,ComponentBase*>::const_iterator cur = components_.find(by_name);
if (cur == components_.end())
return 0;
else
return cur->second;
}
Architecture::Statement::Statement()
{
}

View File

@ -21,6 +21,7 @@
# include "StringHeap.h"
# include "LineInfo.h"
# include "scope.h"
# include <list>
# include <map>
@ -36,7 +37,7 @@ class named_expr_t;
* etc.) of a parsed VHDL architecture. These objects are ultimately
* put into entities.
*/
class Architecture : public LineInfo {
class Architecture : public Scope, public LineInfo {
public:
// Architectures contain concurrent statements, that are
@ -65,7 +66,6 @@ class Architecture : public LineInfo {
~Architecture();
perm_string get_name() const { return name_; }
const ComponentBase* find_component(perm_string by_name);
// Elaborate this architecture in the context of the given entity.
int elaborate(Entity*entity);
@ -83,8 +83,6 @@ class Architecture : public LineInfo {
perm_string name_;
// Signals declared local to this architecture
std::map<perm_string,Signal*> signals_;
// Component declarations...
std::map<perm_string,ComponentBase*> components_;
// Concurrent statements local to this architecture
std::list<Architecture::Statement*> statements_;

View File

@ -76,6 +76,17 @@ void ComponentBase::dump_ports(ostream&out) const
}
}
void Scope::dump_scope(ostream&out) const
{
// Dump component declarations
for (map<perm_string,ComponentBase*>::const_iterator cur = components_.begin()
; cur != components_.end() ; ++cur) {
out << " component " << cur->first << " is" << endl;
cur->second->dump_ports(out);
out << " end component " << cur->first << endl;
}
}
void Entity::dump(ostream&out) const
{
out << "entity " << get_name()
@ -100,13 +111,7 @@ void Architecture::dump(ostream&out, perm_string of_entity) const
cur->second->dump(out);
}
// Dump component declarations
for (map<perm_string,ComponentBase*>::const_iterator cur = components_.begin()
; cur != components_.end() ; ++cur) {
out << " component " << cur->first << " is" << endl;
cur->second->dump_ports(out);
out << " end component " << cur->first << endl;
}
dump_scope(out);
for (list<Architecture::Statement*>::const_iterator cur = statements_.begin()
; cur != statements_.end() ; ++cur) {

105
vhdlpp/library.cc Normal file
View File

@ -0,0 +1,105 @@
/*
* 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_misc.h"
# include "compiler.h"
# include "package.h"
# include <map>
using namespace std;
struct library_contents {
map<perm_string,Package*> packages;
};
static map<perm_string,struct library_contents> libraries;
/*
* This function saves a package into the named library. Create the
* library if necessary.
*/
void library_save_package(const char*libname, Package*pack)
{
if (libname == 0)
libname = "work";
perm_string use_libname = lex_strings.make(libname);
struct library_contents&lib = libraries[use_libname];
lib.packages[pack->name()] = pack;
}
void library_import(const YYLTYPE&loc, const std::list<perm_string>*names)
{
for (std::list<perm_string>::const_iterator cur = names->begin()
; cur != names->end() ; ++cur) {
if (*cur == "ieee") {
// The ieee library is special and handled by an
// internal function.
import_ieee();
} else {
sorrymsg(loc, "library import (%s) not implemented.\n", cur->str());
}
}
}
void library_use(const YYLTYPE&loc, struct library_results&res,
const char*libname, const char*package, const char*name)
{
if (libname == 0) {
errormsg(loc, "error: No library name for this use clause?\n");
return;
}
perm_string use_library = lex_strings.make(libname);
perm_string use_package = lex_strings.make(package);
perm_string use_name = name? lex_strings.make(name) : perm_string::literal("all");
// Special case handling for the IEEE library.
if (use_library == "ieee") {
import_ieee_use(use_package, use_name);
return;
}
struct library_contents&lib = libraries[use_library];
Package*pack = lib.packages[use_package];
if (pack == 0) {
errormsg(loc, "No package %s in library %s\n",
use_package.str(), use_library.str());
return;
}
// We have a package that we are going to extract names
// from. Use the name to get the selected objects, and write
// results into the "res" members.
if (use_name == "all") {
sorrymsg(loc, "Don't support all from package\n");
return;
}
if (ComponentBase*cur = pack->find_component(use_name)) {
res.components.push_back(cur);
return;
}
errormsg(loc, "No such name %s in package %s\n",
use_name.str(), pack->name().str());
}

29
vhdlpp/package.cc Normal file
View File

@ -0,0 +1,29 @@
/*
* 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 "package.h"
Package::Package(perm_string n, map<perm_string,ComponentBase*>&comps)
: Scope(comps), name_(n)
{
}
Package::~Package()
{
}

37
vhdlpp/package.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef __package_H
#define __package_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 "scope.h"
# include "LineInfo.h"
class Package : public Scope, public LineInfo {
public:
Package(perm_string name, std::map<perm_string,ComponentBase*>&comps);
~Package();
perm_string name() const { return name_; }
private:
perm_string name_;
};
#endif

View File

@ -27,6 +27,7 @@
# include "parse_misc.h"
# include "architec.h"
# include "expression.h"
# include "package.h"
# include "vsignal.h"
# include "vtype.h"
# include <cstdarg>
@ -68,9 +69,25 @@ int parse_sorrys = 0;
static map<perm_string, Signal*> block_signals;
/*
* This map accumulates component declarations.
* This map accumulates component declarations. This variable is used
* by rules that build up package, architectures, whatever objects
* can contain component declarations.
*/
static map<perm_string, ComponentBase*> block_components;
/*
* Calls to library_use return a collections of declation objects that
* belong in the scope that is being worked on. This is a convenience
* function for collecting those results into the parser variables.
*/
static void collect_library_results(struct library_results&res)
{
for (list<ComponentBase*>::iterator cur = res.components.begin()
; cur != res.components.end() ; ++cur) {
block_components[(*cur)->get_name()] = *cur;
}
}
%}
@ -288,6 +305,8 @@ block_declarative_item
| component_declaration
| use_clause_lib
/* Various error handling rules for block_declarative_item... */
| K_signal error ';'
@ -796,10 +815,13 @@ package_declaration
errormsg(@1, "Identifier %s doesn't match package name %s.\n",
$7, name.str());
}
Package*tmp = new Package(name, block_components);
FILE_NAME(tmp, @1);
delete[]$2;
if ($7) delete[]$7;
sorrymsg(@1, "Package declarations not supported yet.\n");
block_components.clear();
/* Put this package into the work library. */
library_save_package(0, tmp);
}
| K_package IDENTIFIER K_is error K_end K_package_opt identifier_opt ';'
{ errormsg(@4, "Syntax error in package clause.\n");
@ -952,19 +974,30 @@ selected_names
$$ = tmp;
}
;
/* The *_use variant of selected_name is used by the "use"
clause. It is syntactically identical to other selected_name
rules, but is a convenient place to attach use_clause actions. */
selected_name_use
: IDENTIFIER '.' K_all
{ library_use(@1, 0, $1, 0);
{ struct library_results res;
library_use(@1, res, 0, $1, 0);
delete[]$1;
}
| IDENTIFIER '.' IDENTIFIER '.' K_all
{ library_use(@1, $1, $3, 0);
{ struct library_results res;
library_use(@1, res, $1, $3, 0);
delete[]$1;
delete[]$3;
}
| IDENTIFIER '.' IDENTIFIER '.' IDENTIFIER
{ struct library_results res;
library_use(@1, res, $1, $3, $5);
collect_library_results(res);
delete[]$1;
delete[]$3;
delete[]$5;
}
;
selected_names_use

View File

@ -88,37 +88,3 @@ const VType* calculate_subtype(const char*base_name,
return base_type;
}
void library_import(const YYLTYPE&loc, const std::list<perm_string>*names)
{
for (std::list<perm_string>::const_iterator cur = names->begin()
; cur != names->end() ; ++cur) {
if (*cur == "ieee") {
// The ieee library is special and handled by an
// internal function.
import_ieee();
} else {
errormsg(loc, "sorry: library import (%s) not implemented.\n", cur->str());
}
}
}
void library_use(const YYLTYPE&loc, const char*libname, const char*pack, const char*name)
{
if (libname == 0) {
errormsg(loc, "error: No library name for this use clause?\n");
return;
}
perm_string use_library = lex_strings.make(libname);
perm_string use_package = lex_strings.make(pack);
perm_string use_name = name? lex_strings.make(name) : perm_string::literal("all");
// Special case handling for the IEEE library.
if (use_library == "ieee") {
import_ieee_use(use_package, use_name);
return;
}
errormsg(loc, "sorry: Only the IEEE library is supported,\n");
}

View File

@ -23,6 +23,7 @@
class Architecture;
class Expression;
class Package;
class VType;
extern void bind_architecture_to_entity(const char*ename, Architecture*arch);
@ -32,8 +33,19 @@ extern const VType* calculate_subtype(const char*base_name,
bool downto,
Expression*array_right);
extern void library_save_package(const char*libname, Package*pack);
extern void library_import(const YYLTYPE&loc, const std::list<perm_string>*names);
extern void library_use(const YYLTYPE&loc, const char*libname, const char*pack, const char*ident);
struct library_results {
std::list<ComponentBase*> components;
std::list<const VType*> types;
void clear() {
components.clear();
types.clear();
}
};
extern void library_use(const YYLTYPE&loc, struct library_results&res, const char*libname, const char*pack, const char*ident);
#endif

40
vhdlpp/scope.cc Normal file
View File

@ -0,0 +1,40 @@
/*
* 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 "scope.h"
using namespace std;
Scope::Scope(map<perm_string,ComponentBase*>&comps)
{
components_ = comps;
}
Scope::~Scope()
{
}
ComponentBase* Scope::find_component(perm_string by_name)
{
map<perm_string,ComponentBase*>::const_iterator cur = components_.find(by_name);
if (cur == components_.end())
return 0;
else
return cur->second;
}

45
vhdlpp/scope.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef __scope_H
#define __scope_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 "StringHeap.h"
class ComponentBase;
class VType;
class Scope {
public:
Scope(std::map<perm_string,ComponentBase*>&comps);
~Scope();
ComponentBase* find_component(perm_string by_name);
void dump_scope(ostream&out) const;
private:
// Component declarations...
std::map<perm_string,ComponentBase*> components_;
// Type declarations...
std::map<perm_string,const VType*> types_;
};
#endif