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.
This commit is contained in:
Stephen Williams 2011-04-17 17:19:09 -07:00
parent 303f057de1
commit 3ff7a8f7b0
19 changed files with 613 additions and 226 deletions

View File

@ -23,12 +23,10 @@
using namespace std;
Architecture::Architecture(perm_string name, map<perm_string,Signal*>&sigs,
map<perm_string,ComponentBase*>&comps,
Architecture::Architecture(perm_string name, const ScopeBase&ref,
list<Architecture::Statement*>&s)
: Scope(comps), name_(name)
: Scope(ref), name_(name)
{
signals_ = sigs;
statements_.splice(statements_.end(), s);
}

View File

@ -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<perm_string,Signal*>&sigs,
std::map<perm_string,ComponentBase*>&comps,
Architecture(perm_string name, const ScopeBase&ref,
std::list<Architecture::Statement*>&s);
~Architecture();
@ -81,8 +80,6 @@ class Architecture : public Scope, public LineInfo {
private:
perm_string name_;
// Signals declared local to this architecture
std::map<perm_string,Signal*> signals_;
// Concurrent statements local to this architecture
std::list<Architecture::Statement*> statements_;

View File

@ -25,16 +25,33 @@
# include <typeinfo>
# include <cassert>
int Architecture::emit(ostream&out, Entity*entity)
int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc)
{
int errors = 0;
for (map<perm_string,Signal*>::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<perm_string,struct const_t>::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<Architecture::Statement*>::iterator cur = statements_.begin()
; cur != statements_.end() ; ++cur) {

View File

@ -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<perm_string,Entity*>::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<perm_string,const VType*>::const_iterator cur = types_.begin()
; cur != types_.end() ; ++cur) {
out << " " << cur->first << ": ";
cur->second->show(out);
out << endl;
}
// Dump constants
for (map<perm_string,const_t>::const_iterator cur = constants_.begin()
; cur != constants_.end() ; ++cur) {
out << " constant " << cur->first << " = ";
out << endl;
}
// Dump signal declarations
for (map<perm_string,Signal*>::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<perm_string,ComponentBase*>::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<perm_string,Signal*>::const_iterator cur = signals_.begin()
; cur != signals_.end() ; ++cur) {
cur->second->dump(out, indent+3);
}
dump_scope(out);
for (list<Architecture::Statement*>::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

View File

@ -22,6 +22,7 @@
# include <map>
# include <list>
# include <vector>
# include <iostream>
# 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

View File

@ -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 <iostream>
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)
{

View File

@ -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;

View File

@ -24,13 +24,38 @@
using namespace std;
struct library_contents {
map<perm_string,Package*> packages;
};
static void import_ieee(void);
static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name);
static map<perm_string,struct library_contents> 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, map<perm_string,Package*>packages)
{
for (map<perm_string,Package*>::iterator cur = packages.begin()
; cur != packages.end() ; ++cur) {
dump_library_package(file, lname, cur->first, cur->second);
}
}
void dump_libraries(ostream&file)
{
for (map<perm_string,struct library_contents>::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<perm_string>*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<VTypeArray::range_t> 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<VTypeArray::range_t> dims (1);
res->bind_name(perm_string::literal("signed"),
new VTypeArray(&primitive_STDLOGIC, dims, true));
}
if (all_flag || name == "unsigned") {
vector<VTypeArray::range_t> 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<VTypeArray::range_t> dims (1);
res->bind_name(perm_string::literal("signed"),
new VTypeArray(&primitive_STDLOGIC, dims, true));
}
if (all_flag || name == "unsigned") {
vector<VTypeArray::range_t> 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<VTypeArray::range_t> (1));
const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (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);
}

View File

@ -41,6 +41,7 @@ const char NOTICE[] =
# include "compiler.h"
# include "parse_api.h"
# include "vtype.h"
# include <fstream>
# include <cstdio>
# include <cstdlib>
# include <cstring>
@ -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;

View File

@ -19,8 +19,8 @@
# include "package.h"
Package::Package(perm_string n, map<perm_string,ComponentBase*>&comps)
: Scope(comps), name_(n)
Package::Package(perm_string n, const ScopeBase&ref)
: Scope(ref), name_(n)
{
}

View File

@ -25,7 +25,7 @@
class Package : public Scope, public LineInfo {
public:
Package(perm_string name, std::map<perm_string,ComponentBase*>&comps);
Package(perm_string name, const ScopeBase&ref);
~Package();
perm_string name() const { return name_; }

View File

@ -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<perm_string, Signal*> 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<perm_string, ComponentBase*> block_components;
static ActiveScope*active_scope = new ActiveScope;
static list<ActiveScope*> 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<ComponentBase*>::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 <vtype> subtype_indication
%type <text> architecture_body_start package_declaration_start
%type <text> identifier_opt logical_name suffix
%type <name_list> logical_name_list identifier_list
%type <compound_name> 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<perm_string>::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;
}

View File

@ -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;
}

View File

@ -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<perm_string>*names);
struct library_results {
std::list<ComponentBase*> components;
std::list<const VType*> 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

View File

@ -18,12 +18,67 @@
*/
# include "scope.h"
# include <iostream>
using namespace std;
Scope::Scope(map<perm_string,ComponentBase*>&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<perm_string,const VType*>::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<perm_string,const_t>::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<perm_string,ComponentBase*>::const_iterator cur = that->components_.begin()
; cur != that->components_.end() ; ++ cur) {
if (cur->second == 0)
continue;
components_[cur->first] = cur->second;
}
for (map<perm_string,const VType*>::const_iterator cur = that->types_.begin()
; cur != that->types_.end() ; ++ cur) {
if (cur->second == 0)
continue;
types_[cur->first] = cur->second;
}
for (map<perm_string,const_t>::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<ComponentBase*>&res)
{
for (map<perm_string,ComponentBase*>::const_iterator cur = components_.begin()
; cur != components_.end() ; ++cur) {
if (cur->second == 0)
continue;
res.push_back(cur->second);
}
}

View File

@ -23,26 +23,86 @@
# include <map>
# include "StringHeap.h"
class Architecture;
class ComponentBase;
class Entity;
class Expression;
class Signal;
class VType;
class Scope {
class ScopeBase {
public:
Scope(std::map<perm_string,ComponentBase*>&comps);
~Scope();
ScopeBase() { }
explicit ScopeBase(const ScopeBase&ref);
virtual ~ScopeBase() =0;
ComponentBase* find_component(perm_string by_name);
void collect_components(std::list<ComponentBase*>&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<perm_string,Signal*> signals_;
// Component declarations...
std::map<perm_string,ComponentBase*> components_;
// Type declarations...
std::map<perm_string,const VType*> types_;
// Constant declarations...
struct const_t {
const VType*typ;
Expression*val;
};
std::map<perm_string, struct const_t> 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

View File

@ -18,88 +18,11 @@
*/
# include "vtype.h"
# include <map>
# include <typeinfo>
using namespace std;
std::map<perm_string, const VType*> 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<VTypeArray::range_t> (1));
const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (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<VTypeArray::range_t> 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<VTypeArray::range_t> dims (1);
global_types[perm_string::literal("signed")] = new VTypeArray(&primitive_STDLOGIC, dims, true);
}
if (all_flag || name == "unsigned") {
vector<VTypeArray::range_t> 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<VTypeArray::range_t> dims (1);
global_types[perm_string::literal("signed")] = new VTypeArray(&primitive_STDLOGIC, dims, true);
}
if (all_flag || name == "unsigned") {
vector<VTypeArray::range_t> 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 << "<nil>";
}
VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val)
: base_(base)
{
max_ = max_val;
min_ = min_val;
}
VTypeRange::~VTypeRange()
{
}

View File

@ -20,9 +20,9 @@
*/
# include <iostream>
# include <map>
# include <vector>
# include <climits>
# include <inttypes.h>
# 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<perm_string, const VType*> 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

View File

@ -58,3 +58,8 @@ void VTypePrimitive::elaborate(VType::decl_t&decl) const
break;
}
}
void VTypeRange::elaborate(VType::decl_t&decl) const
{
base_->elaborate(decl);
}