From 3ff7a8f7b0a37c96b5491440f8e77454a0a8d740 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 17 Apr 2011 17:19:09 -0700 Subject: [PATCH] Add support for constants and package types. Significant rework of scope management to unify the handling of types in the ieee library and types/constants/components in packages. This involved adjusting the parser rules to manage a stack of scopes and rewriting the IEEE library support to not use global maps for the loaded types. --- vhdlpp/architec.cc | 6 +- vhdlpp/architec.h | 5 +- vhdlpp/architec_emit.cc | 21 ++++- vhdlpp/debug.cc | 40 +++++++-- vhdlpp/entity.h | 3 +- vhdlpp/expression.cc | 76 +++++++++++++++- vhdlpp/expression.h | 10 ++- vhdlpp/library.cc | 118 +++++++++++++++++++++++-- vhdlpp/main.cc | 17 +++- vhdlpp/package.cc | 4 +- vhdlpp/package.h | 2 +- vhdlpp/parse.y | 180 ++++++++++++++++++++++++++------------ vhdlpp/parse_misc.cc | 55 ++++++++++-- vhdlpp/parse_misc.h | 33 ++++--- vhdlpp/scope.cc | 69 ++++++++++++--- vhdlpp/scope.h | 80 ++++++++++++++--- vhdlpp/vtype.cc | 90 +++---------------- vhdlpp/vtype.h | 25 +++--- vhdlpp/vtype_elaborate.cc | 5 ++ 19 files changed, 613 insertions(+), 226 deletions(-) diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 6d9f47000..7d77ed890 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -23,12 +23,10 @@ using namespace std; -Architecture::Architecture(perm_string name, map&sigs, - map&comps, +Architecture::Architecture(perm_string name, const ScopeBase&ref, list&s) -: Scope(comps), name_(name) +: Scope(ref), name_(name) { - signals_ = sigs; statements_.splice(statements_.end(), s); } diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 0dd208b32..bfe3955ea 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -60,8 +60,7 @@ class Architecture : public Scope, public LineInfo { public: // Create an architecture from its name and its statements. // NOTE: The statement list passed in is emptied. - Architecture(perm_string name, std::map&sigs, - std::map&comps, + Architecture(perm_string name, const ScopeBase&ref, std::list&s); ~Architecture(); @@ -81,8 +80,6 @@ class Architecture : public Scope, public LineInfo { private: perm_string name_; - // Signals declared local to this architecture - std::map signals_; // Concurrent statements local to this architecture std::list statements_; diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 7809de885..d7f77625d 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -25,16 +25,33 @@ # include # include -int Architecture::emit(ostream&out, Entity*entity) +int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc) { int errors = 0; for (map::iterator cur = signals_.begin() ; cur != signals_.end() ; ++cur) { - errors += cur->second->emit(out, entity, this); + errors += cur->second->emit(out, entity, arc); } + return errors; +} + +int Architecture::emit(ostream&out, Entity*entity) +{ + int errors = 0; + + for (map::iterator cur = constants_.begin() + ; cur != constants_.end() ; ++cur) { + + out << "localparam " << cur->first << " = "; + errors += cur->second.val->emit(out, entity, this); + out << ";" << endl; + } + + errors += emit_signals(out, entity, this); + for (list::iterator cur = statements_.begin() ; cur != statements_.end() ; ++cur) { diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 934c1494a..0c6181290 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -46,9 +46,8 @@ static ostream& operator << (ostream&out, port_mode_t that) return out; } -void dump_design_entities(const char*path) +void dump_design_entities(ostream&file) { - ofstream file (path); for (map::iterator cur = design_entities.begin() ; cur != design_entities.end() ; ++cur) { cur->second->dump(file); @@ -78,6 +77,30 @@ void ComponentBase::dump_ports(ostream&out, int indent) const void Scope::dump_scope(ostream&out) const { + // Dump types + for (map::const_iterator cur = types_.begin() + ; cur != types_.end() ; ++cur) { + out << " " << cur->first << ": "; + cur->second->show(out); + out << endl; + } + + // Dump constants + for (map::const_iterator cur = constants_.begin() + ; cur != constants_.end() ; ++cur) { + out << " constant " << cur->first << " = "; + out << endl; + } + + // Dump signal declarations + for (map::const_iterator cur = signals_.begin() + ; cur != signals_.end() ; ++cur) { + if (cur->second) + cur->second->dump(out, 3); + else + out << " signal " << cur->first.str() << ": ???" << endl; + } + // Dump component declarations for (map::const_iterator cur = components_.begin() ; cur != components_.end() ; ++cur) { @@ -105,12 +128,6 @@ void Architecture::dump(ostream&out, perm_string of_entity, int indent) const << " of entity " << of_entity << " file=" << get_fileline() << endl; - // Dump signal declarations - for (map::const_iterator cur = signals_.begin() - ; cur != signals_.end() ; ++cur) { - cur->second->dump(out, indent+3); - } - dump_scope(out); for (list::const_iterator cur = statements_.begin() @@ -126,7 +143,12 @@ void Architecture::Statement::dump(ostream&out, int indent) const void Signal::dump(ostream&out, int indent) const { - out << setw(indent) << "" << "signal " << name_ << " is " << *type_ << endl; + out << setw(indent) << "" << "signal " << name_ << " is "; + if (type_) + out << *type_; + else + out << "?NO TYPE?"; + out << endl; } void SignalAssignment::dump(ostream&out, int indent) const diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index c56f10d84..96780546b 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -22,6 +22,7 @@ # include # include # include +# include # include "StringHeap.h" # include "LineInfo.h" # include "vtype.h" @@ -123,6 +124,6 @@ extern int emit_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); +extern void dump_design_entities(ostream&file); #endif diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index fa7cac5f3..3c2579aad 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -17,7 +17,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -# include "expression.h" +# include "expression.h" +# include "scope.h" +# include + +using namespace std; Expression::Expression() { @@ -27,7 +31,7 @@ Expression::~Expression() { } -bool Expression::evaluate(int64_t&) const +bool Expression::evaluate(ScopeBase*, int64_t&) const { return false; } @@ -43,6 +47,16 @@ ExpBinary::~ExpBinary() delete operand2_; } +bool ExpBinary::eval_operand1(ScopeBase*scope, int64_t&val) const +{ + return operand1_->evaluate(scope, val); +} + +bool ExpBinary::eval_operand2(ScopeBase*scope, int64_t&val) const +{ + return operand2_->evaluate(scope, val); +} + ExpUnary::ExpUnary(Expression*op1) : operand1_(op1) { @@ -62,6 +76,48 @@ ExpArithmetic::~ExpArithmetic() { } +bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const +{ + int64_t val1, val2; + bool rc; + + rc = eval_operand1(scope, val1); + if (rc == false) + return false; + + rc = eval_operand2(scope, val2); + if (rc == false) + return false; + + switch (fun_) { + case PLUS: + val = val1 + val2; + break; + case MINUS: + val = val1 - val2; + break; + case MULT: + val = val1 * val2; + break; + case DIV: + if (val2 == 0) + return false; + val = val1 / val2; + break; + case MOD: + if (val2 == 0) + return false; + val = val1 % val2; + break; + case REM: + return false; + case POW: + return false; + } + + return true; +} + ExpInteger::ExpInteger(int64_t val) : value_(val) { @@ -71,7 +127,7 @@ ExpInteger::~ExpInteger() { } -bool ExpInteger::evaluate(int64_t&val) const +bool ExpInteger::evaluate(ScopeBase*, int64_t&val) const { val = value_; return true; @@ -106,6 +162,20 @@ const char* ExpName::name() const return name_; } +bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const +{ + const VType*type; + Expression*exp; + + bool rc = scope->find_constant(name_, type, exp); + if (rc == false) { + cerr << "XXXX Unable to evaluate name " << name_ << "." << endl; + return false; + } + + return exp->evaluate(scope, val); +} + ExpUAbs::ExpUAbs(Expression*op1) : ExpUnary(op1) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index cf5ae5fdd..8b4db80a6 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -25,6 +25,7 @@ class Entity; class Architecture; +class ScopeBase; /* * The Expression class represents parsed expressions from the parsed @@ -46,7 +47,7 @@ class Expression : public LineInfo { // to constant literal values. Return true and set the val // argument if the evaluation works, or return false if it // cannot be done. - virtual bool evaluate(int64_t&val) const; + virtual bool evaluate(ScopeBase*scope, int64_t&val) const; // This method returns true if the drawn Verilog for this // expression is a primary. A containing expression can use @@ -94,6 +95,9 @@ class ExpBinary : public Expression { int emit_operand1(ostream&out, Entity*ent, Architecture*arc); int emit_operand2(ostream&out, Entity*ent, Architecture*arc); + bool eval_operand1(ScopeBase*scope, int64_t&val) const; + bool eval_operand2(ScopeBase*scope, int64_t&val) const; + void dump_operands(ostream&out, int indent = 0) const; private: @@ -111,6 +115,7 @@ class ExpArithmetic : public ExpBinary { ~ExpArithmetic(); int emit(ostream&out, Entity*ent, Architecture*arc); + virtual bool evaluate(ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; private: @@ -125,7 +130,7 @@ class ExpInteger : public Expression { int emit(ostream&out, Entity*ent, Architecture*arc); bool is_primary(void) const; - bool evaluate(int64_t&val) const; + bool evaluate(ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; private: @@ -162,6 +167,7 @@ class ExpName : public Expression { public: // Base methods int emit(ostream&out, Entity*ent, Architecture*arc); bool is_primary(void) const; + bool evaluate(ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; const char* name() const; diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index cbed2db2d..67511b4ef 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -24,13 +24,38 @@ using namespace std; - struct library_contents { map packages; }; +static void import_ieee(void); +static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name); + static map libraries; +static void dump_library_package(ostream&file, perm_string lname, perm_string pname, Package*pack) +{ + file << "package " << lname << "." << pname << endl; + pack->dump_scope(file); + file << "end package " << lname << "." << pname << endl; +} + +static void dump_library_packages(ostream&file, perm_string lname, mappackages) +{ + for (map::iterator cur = packages.begin() + ; cur != packages.end() ; ++cur) { + dump_library_package(file, lname, cur->first, cur->second); + } +} + +void dump_libraries(ostream&file) +{ + for (map::iterator cur = libraries.begin() + ; cur != libraries.end() ; ++cur) { + dump_library_packages(file, cur->first, cur->second.packages); + } +} + /* * This function saves a package into the named library. Create the * library if necessary. @@ -60,7 +85,7 @@ void library_import(const YYLTYPE&loc, const std::list*names) } } -void library_use(const YYLTYPE&loc, struct library_results&res, +void library_use(const YYLTYPE&loc, ActiveScope*res, const char*libname, const char*package, const char*name) { if (libname == 0) { @@ -74,7 +99,7 @@ void library_use(const YYLTYPE&loc, struct library_results&res, // Special case handling for the IEEE library. if (use_library == "ieee") { - import_ieee_use(use_package, use_name); + import_ieee_use(res, use_package, use_name); return; } @@ -91,15 +116,98 @@ void library_use(const YYLTYPE&loc, struct library_results&res, // results into the "res" members. if (use_name == "all") { - pack->collect_components(res.components); + res->use_from(pack); return; } if (ComponentBase*cur = pack->find_component(use_name)) { - res.components.push_back(cur); + res->bind_name(use_name, cur); return; } errormsg(loc, "No such name %s in package %s\n", use_name.str(), pack->name().str()); } + +static void import_ieee(void) +{ +} + +static void import_ieee_use_std_logic_1164(ActiveScope*res, perm_string name) +{ + bool all_flag = name=="all"; + + if (all_flag || name == "std_logic_vector") { + vector dims (1); + res->bind_name(perm_string::literal("std_logic_vector"), + new VTypeArray(&primitive_STDLOGIC, dims, false)); + } +} + +static void import_ieee_use_numeric_bit(ActiveScope*res, perm_string name) +{ + bool all_flag = name=="all"; + + if (all_flag || name == "signed") { + vector dims (1); + res->bind_name(perm_string::literal("signed"), + new VTypeArray(&primitive_STDLOGIC, dims, true)); + } + if (all_flag || name == "unsigned") { + vector dims (1); + res->bind_name(perm_string::literal("unsigned"), + new VTypeArray(&primitive_BIT, dims, false)); + } +} + +static void import_ieee_use_numeric_std(ActiveScope*res, perm_string name) +{ + bool all_flag = name=="all"; + + if (all_flag || name == "signed") { + vector dims (1); + res->bind_name(perm_string::literal("signed"), + new VTypeArray(&primitive_STDLOGIC, dims, true)); + } + if (all_flag || name == "unsigned") { + vector dims (1); + res->bind_name(perm_string::literal("unsigned"), + new VTypeArray(&primitive_STDLOGIC, dims, false)); + } +} + +static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name) +{ + if (package == "std_logic_1164") { + import_ieee_use_std_logic_1164(res, name); + return; + } + + if (package == "numeric_bit") { + import_ieee_use_numeric_bit(res, name); + return; + } + + if (package == "numeric_std") { + import_ieee_use_numeric_std(res, name); + return; + } +} + + +const VTypePrimitive primitive_BOOLEAN (VTypePrimitive::BOOLEAN); +const VTypePrimitive primitive_BIT (VTypePrimitive::BIT); +const VTypePrimitive primitive_INTEGER (VTypePrimitive::INTEGER); +const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC); + +const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); +const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); + +void generate_global_types(ActiveScope*res) +{ + res->bind_name(perm_string::literal("boolean"), &primitive_BOOLEAN); + res->bind_name(perm_string::literal("bit"), &primitive_BIT); + res->bind_name(perm_string::literal("integer"), &primitive_INTEGER); + res->bind_name(perm_string::literal("std_logic"), &primitive_STDLOGIC); + res->bind_name(perm_string::literal("bit_vector"),&primitive_BOOL_VECTOR); +} diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index eedc0b9e9..87e4cd9cf 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -41,6 +41,7 @@ const char NOTICE[] = # include "compiler.h" # include "parse_api.h" # include "vtype.h" +# include # include # include # include @@ -52,6 +53,9 @@ const char NOTICE[] = bool verbose_flag = false; // Where to dump design entities 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) { @@ -61,6 +65,8 @@ static void process_debug_token(const char*word) yydebug = 0; } else if (strncmp(word, "entities=", 9) == 0) { dump_design_entities_path = strdup(word+9); + } else if (strncmp(word, "libraries=", 10) == 0) { + dump_libraries_path = strdup(word+10); } } @@ -125,8 +131,15 @@ int main(int argc, char*argv[]) } } - if (dump_design_entities_path) - dump_design_entities(dump_design_entities_path); + if (dump_libraries_path) { + ofstream file(dump_libraries_path); + dump_libraries(file); + } + + if (dump_design_entities_path) { + ofstream file(dump_design_entities_path); + dump_design_entities(file); + } if (errors > 0) return 2; diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 1ca6b55e7..936464569 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -19,8 +19,8 @@ # include "package.h" -Package::Package(perm_string n, map&comps) -: Scope(comps), name_(n) +Package::Package(perm_string n, const ScopeBase&ref) +: Scope(ref), name_(n) { } diff --git a/vhdlpp/package.h b/vhdlpp/package.h index 0bfa0c909..a56e176d5 100644 --- a/vhdlpp/package.h +++ b/vhdlpp/package.h @@ -25,7 +25,7 @@ class Package : public Scope, public LineInfo { public: - Package(perm_string name, std::map&comps); + Package(perm_string name, const ScopeBase&ref); ~Package(); perm_string name() const { return name_; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index dfb814413..5fc437eaf 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -61,31 +61,46 @@ static void yyerror(const char*msg); int parse_errors = 0; int parse_sorrys = 0; -/* - * This map accumulates signals that are matched in the declarations - * section of a block. When the declarations are over, these are - * transferred to a map for the block proper. - */ -static map block_signals; /* - * This map accumulates component declarations. This variable is used - * by rules that build up package, architectures, whatever objects - * can contain component declarations. + * Create an initial scope that collects all the global + * declarations. Also save a stack of previous scopes, as a way to + * manage lexical scopes. */ -static map block_components; +static ActiveScope*active_scope = new ActiveScope; +static list scope_stack; /* - * 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. + * When a scope boundary starts, call the push_scope function to push + * a scope context. Preload this scope context with the contents of + * the parent scope, then make this the current scope. When the scope + * is done, the pop_scope function pops the scope off the stack and + * resumes the scope that was the parent. */ -static void collect_library_results(struct library_results&res) +static void push_scope(void) { - for (list::iterator cur = res.components.begin() - ; cur != res.components.end() ; ++cur) { - block_components[(*cur)->get_name()] = *cur; - } + assert(active_scope); + scope_stack.push_front(active_scope); + active_scope = new ActiveScope (active_scope); +} + +static void pop_scope(void) +{ + delete active_scope; + assert(scope_stack.size() > 0); + active_scope = scope_stack.front(); + scope_stack.pop_front(); +} + + +void preload_global_types(void) +{ + generate_global_types(active_scope); +} + +const VType*parse_type_by_name(perm_string name) +{ + return active_scope->find_type(name); } %} @@ -182,6 +197,7 @@ static void collect_library_results(struct library_results&res) %type subtype_indication +%type architecture_body_start package_declaration_start %type identifier_opt logical_name suffix %type logical_name_list identifier_list %type prefix selected_name @@ -193,33 +209,38 @@ static void collect_library_results(struct library_results&res) design_file : design_units ; architecture_body - : K_architecture IDENTIFIER + : architecture_body_start K_of IDENTIFIER K_is block_declarative_items_opt K_begin architecture_statement_part K_end K_architecture_opt identifier_opt ';' - { Architecture*tmp = new Architecture(lex_strings.make($2), - block_signals, - block_components, *$8); + { Architecture*tmp = new Architecture(lex_strings.make($1), + *active_scope, *$7); FILE_NAME(tmp, @1); - bind_architecture_to_entity($4, tmp); - if ($11 && tmp->get_name() != $11) - errormsg(@2, "Architecture name doesn't match closing name.\n"); - delete[]$2; - delete[]$4; - delete $8; - block_signals.clear(); - block_components.clear(); - if ($11) delete[]$11; + bind_architecture_to_entity($3, tmp); + if ($10 && tmp->get_name() != $10) + errormsg(@1, "Architecture name doesn't match closing name.\n"); + delete[]$1; + delete[]$3; + delete $7; + pop_scope(); + if ($10) delete[]$10; } - | K_architecture IDENTIFIER + | architecture_body_start K_of IDENTIFIER K_is block_declarative_items_opt K_begin error K_end K_architecture_opt identifier_opt ';' - { errormsg(@8, "Errors in architecture statements.\n"); yyerrok; } - | K_architecture error ';' - { errormsg(@2, "Errors in architecture body.\n"); yyerrok; } + { errormsg(@8, "Errors in architecture statements.\n"); + yyerrok; + pop_scope(); + } ; +architecture_body_start + : K_architecture IDENTIFIER + { $$ = $2; + push_scope(); + } + ; /* * The architecture_statement_part is a list of concurrent * statements. @@ -298,13 +319,15 @@ block_declarative_item ; cur != $2->end() ; ++cur) { Signal*sig = new Signal(*cur, $4); FILE_NAME(sig, @1); - block_signals[*cur] = sig; + active_scope->bind_name(*cur, sig); } delete $2; } | component_declaration + | constant_declaration + { sorrymsg(@1, "constant declarations not supported here.\n"); } | use_clause_lib /* Various error handling rules for block_declarative_item... */ @@ -360,7 +383,7 @@ component_declaration ComponentBase*comp = new ComponentBase(name); if ($4) comp->set_interface($4); - block_components[name] = comp; + active_scope->bind_name(name, comp); delete[]$2; if ($7) delete[] $7; } @@ -470,6 +493,21 @@ configuration_items_opt | ; +constant_declaration + : K_constant identifier_list ':' subtype_indication VASSIGN expression ';' + { // The syntax allows mutliple names to have the same type/value. + for (std::list::iterator cur = $2->begin() + ; cur != $2->end() ; ++cur) { + active_scope->bind_name(*cur, $4, $6); + } + delete $2; + } + | K_constant identifier_list ':' subtype_indication ';' + { sorrymsg(@1, "Deferred constant declarations not supported\n"); + delete $2; + } + ; + context_clause : context_items | ; context_item @@ -807,28 +845,36 @@ name ; package_declaration - : K_package IDENTIFIER K_is + : package_declaration_start K_is package_declarative_part_opt K_end K_package_opt identifier_opt ';' - { perm_string name = lex_strings.make($2); - if($7 && name != $7) { + { perm_string name = lex_strings.make($1); + if($6 && name != $6) { errormsg(@1, "Identifier %s doesn't match package name %s.\n", - $7, name.str()); + $6, name.str()); } - Package*tmp = new Package(name, block_components); + Package*tmp = new Package(name, *active_scope); FILE_NAME(tmp, @1); - delete[]$2; - if ($7) delete[]$7; - block_components.clear(); + delete[]$1; + if ($6) delete[]$6; + pop_scope(); /* 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"); + | package_declaration_start K_is error K_end K_package_opt identifier_opt ';' + { errormsg(@3, "Syntax error in package clause.\n"); yyerrok; + pop_scope(); } ; +package_declaration_start + : K_package IDENTIFIER + { push_scope(); + $$ = $2; + } + ; + /* TODO: this list must be extended in the future presently it is only a sketch */ package_body_declarative_item @@ -846,6 +892,8 @@ package_body_declarative_part_opt package_declarative_item : component_declaration + | constant_declaration + | subtype_declaration | use_clause ; @@ -980,22 +1028,16 @@ selected_names rules, but is a convenient place to attach use_clause actions. */ selected_name_use : IDENTIFIER '.' K_all - { struct library_results res; - library_use(@1, res, 0, $1, 0); - collect_library_results(res); + { library_use(@1, active_scope, 0, $1, 0); delete[]$1; } | IDENTIFIER '.' IDENTIFIER '.' K_all - { struct library_results res; - library_use(@1, res, $1, $3, 0); - collect_library_results(res); + { library_use(@1, active_scope, $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); + { library_use(@1, active_scope, $1, $3, $5); delete[]$1; delete[]$3; delete[]$5; @@ -1024,14 +1066,36 @@ simple_expression } ; +subtype_declaration + : K_subtype IDENTIFIER K_is subtype_indication ';' + { perm_string name = lex_strings.make($2); + if ($4 == 0) { + errormsg(@1, "Failed to declare type name %s.\n", name.str()); + } else { + active_scope->bind_name(name, $4); + } + } + ; + subtype_indication : IDENTIFIER - { const VType*tmp = global_types[lex_strings.make($1)]; + { const VType*tmp = parse_type_by_name(lex_strings.make($1)); delete[]$1; $$ = tmp; } | IDENTIFIER '(' simple_expression direction simple_expression ')' - { const VType*tmp = calculate_subtype($1, $3, $4, $5); + { const VType*tmp = calculate_subtype_array(@1, $1, active_scope, $3, $4, $5); + if (tmp == 0) { + errormsg(@1, "Unable to calculate bounds for array of %s.\n", $1); + } + delete[]$1; + $$ = tmp; + } + | IDENTIFIER K_range simple_expression direction simple_expression + { const VType*tmp = calculate_subtype_range(@1, $1, active_scope, $3, $4, $5); + if (tmp == 0) { + errormsg(@1, "Unable to calculate bounds for range of %s.\n", $1); + } delete[]$1; $$ = tmp; } diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index c376c3b05..a7a972d88 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -54,12 +54,18 @@ void bind_architecture_to_entity(const char*ename, Architecture*arch) } } -const VType* calculate_subtype(const char*base_name, - Expression*array_left, - bool downto, - Expression*array_right) +const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name, + ScopeBase*scope, + Expression*array_left, + bool downto, + Expression*array_right) { - const VType*base_type = global_types[lex_strings.make(base_name)]; + const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); + + if (base_type == 0) { + errormsg(loc, "Unable to find base type %s of array.\n", base_name); + return 0; + } assert(array_left==0 || array_right!=0); @@ -74,11 +80,13 @@ const VType* calculate_subtype(const char*base_name, int64_t left_val; int64_t right_val; - bool rc = array_left->evaluate(left_val); - assert(rc); + bool rc = array_left->evaluate(scope, left_val); + if (rc == false) + return 0; - rc = array_right->evaluate(right_val); - assert(rc); + rc = array_right->evaluate(scope, right_val); + if (rc == false) + return 0; range[0] = VTypeArray::range_t(left_val, right_val); @@ -88,3 +96,32 @@ const VType* calculate_subtype(const char*base_name, return base_type; } + +const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name, + ScopeBase*scope, + Expression*range_left, + bool downto, + Expression*range_right) +{ + const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); + + if (base_type == 0) { + errormsg(loc, "Unable to find base type %s of range.\n", base_name); + return 0; + } + + assert(range_left && range_right); + + int64_t left_val, right_val; + bool rc = range_left->evaluate(scope, left_val); + if (rc == false) + return 0; + + rc = range_right->evaluate(scope, right_val); + if (rc == false) + return 0; + + VTypeRange*sub_type = new VTypeRange(base_type, left_val, right_val); + + return sub_type; +} diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h index dbea11861..de220b4e7 100644 --- a/vhdlpp/parse_misc.h +++ b/vhdlpp/parse_misc.h @@ -21,31 +21,38 @@ # include "parse_api.h" +class ActiveScope; class Architecture; class Expression; class Package; +class ScopeBase; class VType; extern void bind_architecture_to_entity(const char*ename, Architecture*arch); -extern const VType* calculate_subtype(const char*base_name, - Expression*array_left, - bool downto, - Expression*array_right); +extern const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name, + ScopeBase*scope, + Expression*array_left, + bool downto, + Expression*array_right); +extern const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name, + ScopeBase*scope, + Expression*range_left, + bool downto, + Expression*range_right); + +/* + * This function searches the currently active scope, or the global + * scope, for the named type. + */ +extern const VType* parse_type_by_name(perm_string name); extern void library_save_package(const char*libname, Package*pack); extern void library_import(const YYLTYPE&loc, const std::list*names); -struct library_results { - std::list components; - std::list types; +extern void library_use(const YYLTYPE&loc, ActiveScope*res, const char*libname, const char*pack, const char*ident); - void clear() { - components.clear(); - types.clear(); - } -}; +extern void generate_global_types(ActiveScope*res); -extern void library_use(const YYLTYPE&loc, struct library_results&res, const char*libname, const char*pack, const char*ident); #endif diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index edf0b49d7..4df3ed487 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -18,12 +18,67 @@ */ # include "scope.h" +# include using namespace std; -Scope::Scope(map&comps) +ScopeBase::ScopeBase(const ScopeBase&ref) +{ + constants_ = ref.constants_; + signals_ = ref.signals_; + components_ = ref.components_; + types_ = ref.types_; +} + +ScopeBase::~ScopeBase() +{ +} + +const VType*ScopeBase::find_type(perm_string by_name) +{ + map::const_iterator cur = types_.find(by_name); + if (cur == types_.end()) + return 0; + else + return cur->second; +} + +bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) +{ + map::const_iterator cur = constants_.find(by_name); + if (cur == constants_.end()) + return false; + + typ = cur->second.typ; + exp = cur->second.val; + return true; +} + +void ScopeBase::do_use_from(const ScopeBase*that) +{ + for (map::const_iterator cur = that->components_.begin() + ; cur != that->components_.end() ; ++ cur) { + if (cur->second == 0) + continue; + components_[cur->first] = cur->second; + } + + for (map::const_iterator cur = that->types_.begin() + ; cur != that->types_.end() ; ++ cur) { + if (cur->second == 0) + continue; + types_[cur->first] = cur->second; + } + + for (map::const_iterator cur = that->constants_.begin() + ; cur != that->constants_.end() ; ++ cur) { + constants_[cur->first] = cur->second; + } +} + +Scope::Scope(const ScopeBase&ref) +: ScopeBase(ref) { - components_ = comps; } Scope::~Scope() @@ -38,13 +93,3 @@ ComponentBase* Scope::find_component(perm_string by_name) else return cur->second; } - -void Scope::collect_components(list&res) -{ - for (map::const_iterator cur = components_.begin() - ; cur != components_.end() ; ++cur) { - if (cur->second == 0) - continue; - res.push_back(cur->second); - } -} diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index fce58536b..72187fcb6 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -23,26 +23,86 @@ # include # include "StringHeap.h" +class Architecture; class ComponentBase; +class Entity; +class Expression; +class Signal; class VType; -class Scope { +class ScopeBase { public: - Scope(std::map&comps); - ~Scope(); + ScopeBase() { } + explicit ScopeBase(const ScopeBase&ref); + virtual ~ScopeBase() =0; - ComponentBase* find_component(perm_string by_name); - - void collect_components(std::list&res); - - void dump_scope(ostream&out) const; - - private: + const VType* find_type(perm_string by_name); + bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp); + protected: + // Signal declarations... + std::map signals_; // Component declarations... std::map components_; // Type declarations... std::map types_; + // Constant declarations... + struct const_t { + const VType*typ; + Expression*val; + }; + std::map constants_; + + void do_use_from(const ScopeBase*that); +}; + +class Scope : public ScopeBase { + + public: + Scope(const ScopeBase&ref); + ~Scope(); + + ComponentBase* find_component(perm_string by_name); + + public: + void dump_scope(ostream&out) const; + + protected: + // Helper method for emitting signals in the scope. + int emit_signals(ostream&out, Entity*ent, Architecture*arc); +}; + +/* + * The active_scope object accumulates declarations for the scope that + * is in the process of being parsed. When the declarations are over, + * they are transferred over to the specific scope. The ActiveScope is + * used by the parser to build up scopes. + */ +class ActiveScope : public ScopeBase { + + public: + ActiveScope() { } + ActiveScope(ActiveScope*par) : ScopeBase(*par) { } + + ~ActiveScope() { } + + void use_from(const ScopeBase*that) { do_use_from(that); } + + void bind_name(perm_string name, Signal*obj) + { signals_[name] = obj; } + + void bind_name(perm_string name, ComponentBase*obj) + { components_[name] = obj; } + + void bind_name(perm_string name, const VType*obj) + { types_[name] = obj; } + + void bind_name(perm_string name, const VType*obj, Expression*val) + { + const_t&tmp = constants_[name]; + tmp.typ = obj; + tmp.val = val; + } }; #endif diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index ea2db72c8..1065e2592 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -18,88 +18,11 @@ */ # include "vtype.h" +# include # include using namespace std; -std::map global_types; - -const VTypePrimitive primitive_BOOLEAN (VTypePrimitive::BOOLEAN); -const VTypePrimitive primitive_BIT (VTypePrimitive::BIT);; -const VTypePrimitive primitive_INTEGER (VTypePrimitive::INTEGER);; -const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC);; - -const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); -const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); - -void preload_global_types(void) -{ - global_types[perm_string::literal("boolean")] = &primitive_BOOLEAN; - global_types[perm_string::literal("bit")] = &primitive_BIT; - global_types[perm_string::literal("integer")] = &primitive_INTEGER; - global_types[perm_string::literal("std_logic")] = &primitive_STDLOGIC; - global_types[perm_string::literal("bit_vector")]= &primitive_BOOL_VECTOR; -} - -void import_ieee(void) -{ -} - -static void import_ieee_use_std_logic_1164(perm_string name) -{ - bool all_flag = name=="all"; - - if (all_flag || name == "std_logic_vector") { - vector dims (1); - global_types[perm_string::literal("std_logic_vector")] = new VTypeArray(&primitive_STDLOGIC, dims, false); - } -} - -static void import_ieee_use_numeric_bit(perm_string name) -{ - bool all_flag = name=="all"; - - if (all_flag || name == "signed") { - vector dims (1); - global_types[perm_string::literal("signed")] = new VTypeArray(&primitive_STDLOGIC, dims, true); - } - if (all_flag || name == "unsigned") { - vector dims (1); - global_types[perm_string::literal("unsigned")] = new VTypeArray(&primitive_BIT, dims, false); - } -} - -static void import_ieee_use_numeric_std(perm_string name) -{ - bool all_flag = name=="all"; - - if (all_flag || name == "signed") { - vector dims (1); - global_types[perm_string::literal("signed")] = new VTypeArray(&primitive_STDLOGIC, dims, true); - } - if (all_flag || name == "unsigned") { - vector dims (1); - global_types[perm_string::literal("unsigned")] = new VTypeArray(&primitive_STDLOGIC, dims, false); - } -} - -void import_ieee_use(perm_string package, perm_string name) -{ - if (package == "std_logic_1164") { - import_ieee_use_std_logic_1164(name); - return; - } - - if (package == "numeric_bit") { - import_ieee_use_numeric_bit(name); - return; - } - - if (package == "numeric_std") { - import_ieee_use_numeric_std(name); - return; - } -} VType::~VType() { @@ -171,3 +94,14 @@ void VTypeArray::show(ostream&out) const else out << ""; } + +VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val) +: base_(base) +{ + max_ = max_val; + min_ = min_val; +} + +VTypeRange::~VTypeRange() +{ +} diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index de000fb74..9488a9ae6 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -20,9 +20,9 @@ */ # include -# include # include # include +# include # include "StringHeap.h" /* @@ -58,18 +58,8 @@ inline std::ostream&operator << (std::ostream&out, const VType&item) return out; } -/* - * The global_types variable maps type names to a type - * definition. This is after the "use" statements bring in the types - * in included packages. - */ -extern std::map global_types; - extern void preload_global_types(void); -extern void import_ieee(void); -extern void import_ieee_use(perm_string package, perm_string name); - /* * This class represents the primative types that are available to the * type subsystem. @@ -143,4 +133,17 @@ class VTypeArray : public VType { bool signed_flag_; }; +class VTypeRange : public VType { + + public: + VTypeRange(const VType*base, int64_t max_val, int64_t min_val); + ~VTypeRange(); + + virtual void elaborate(decl_t&decl) const; + + private: + const VType*base_; + int64_t max_, min_; +}; + #endif diff --git a/vhdlpp/vtype_elaborate.cc b/vhdlpp/vtype_elaborate.cc index b396cc034..b608e8e1a 100644 --- a/vhdlpp/vtype_elaborate.cc +++ b/vhdlpp/vtype_elaborate.cc @@ -58,3 +58,8 @@ void VTypePrimitive::elaborate(VType::decl_t&decl) const break; } } + +void VTypeRange::elaborate(VType::decl_t&decl) const +{ + base_->elaborate(decl); +}