From 162b26c101c3d16a56d5a2e8802bc754d248c074 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 27 Mar 2011 12:01:58 -0700 Subject: [PATCH] Add more complete support for vhdl local signals. These signals are declared in the architecture and are local to the module. The Architecture already parsed and stored these signal declarations, but this patch adds the ability to actually emit these signals in the generated code. In the process of doing this, I had to regularize the elaboration and emit of VTypes, so that it can be used in multiple places, not just in entity headers (for ports). I also added support for bit selects of signals. This effected a couple places in the parser, and expressions in general. --- vhdlpp/Makefile.in | 7 +++-- vhdlpp/architec.cc | 4 +-- vhdlpp/architec.h | 8 +++-- vhdlpp/architec_elaborate.cc | 29 +++++++++++++++++ vhdlpp/architec_emit.cc | 12 +++++++- vhdlpp/debug.cc | 5 ++- vhdlpp/entity.h | 10 ++---- vhdlpp/entity_elaborate.cc | 54 +++----------------------------- vhdlpp/entity_emit.cc | 28 ++--------------- vhdlpp/expression.cc | 8 ++++- vhdlpp/expression.h | 3 ++ vhdlpp/expression_emit.cc | 8 ++++- vhdlpp/parse.y | 28 +++++++++-------- vhdlpp/vsignal.cc | 14 +++++++++ vhdlpp/vsignal.h | 4 +++ vhdlpp/vtype.h | 15 +++++++++ vhdlpp/vtype_elaborate.cc | 60 ++++++++++++++++++++++++++++++++++++ vhdlpp/vtype_emit.cc | 53 +++++++++++++++++++++++++++++++ 18 files changed, 245 insertions(+), 105 deletions(-) create mode 100644 vhdlpp/architec_elaborate.cc create mode 100644 vhdlpp/vtype_elaborate.cc create mode 100644 vhdlpp/vtype_emit.cc diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index 0fc330b40..1cacd3e45 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -59,10 +59,11 @@ LIBS = @LIBS@ @EXTRALIBS@ M = StringHeap.o LineInfo.o -O = main.o architec.o compiler.o entity.o entity_elaborate.o \ - expression.o vsignal.o vtype.o lexor.o lexor_keyword.o parse.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 \ + lexor.o lexor_keyword.o parse.o \ parse_misc.o vhdlreal.o vhdlint.o debug.o \ - architec_emit.o entity_emit.o expression_emit.o \ + architec_emit.o entity_emit.o expression_emit.o vtype_emit.o \ $M all: dep vhdlpp@EXEEXT@ diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 7a67b9ae5..cacee181a 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -44,8 +44,8 @@ Architecture::Statement::~Statement() { } -SignalAssignment::SignalAssignment(perm_string targ_name, list&rv) -: target_name_(targ_name) +SignalAssignment::SignalAssignment(ExpName*name, list&rv) +: lval_(name) { rval_.splice(rval_.end(), rv); } diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index ec1342ad2..9b25bc2ad 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -27,6 +27,7 @@ class ComponentBase; class Entity; class Expression; +class ExpName; class Signal; /* @@ -63,6 +64,9 @@ class Architecture : public LineInfo { perm_string get_name() const { return name_; } + // Elaborate this architecture in the context of the given entity. + int elaborate(Entity*entity); + // Emit this architecture to the given out file in the context // of the specified entity. This method is used by the // elaborate code to display generated code to the specified @@ -91,14 +95,14 @@ class Architecture : public LineInfo { class SignalAssignment : public Architecture::Statement { public: - SignalAssignment(perm_string target_name, std::list&rval); + SignalAssignment(ExpName*target, std::list&rval); ~SignalAssignment(); int emit(ostream&out, Entity*entity, Architecture*arc); virtual void dump(ostream&out) const; private: - perm_string target_name_; + ExpName*lval_; std::list rval_; }; diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc new file mode 100644 index 000000000..c815d05ea --- /dev/null +++ b/vhdlpp/architec_elaborate.cc @@ -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 "architec.h" +# include "entity.h" +# include "expression.h" +# include +# include + +int Architecture::elaborate(Entity*entity) +{ + return 0; +} diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index d71f45386..888e1fad7 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -20,6 +20,7 @@ # include "architec.h" # include "entity.h" # include "expression.h" +# include "vsignal.h" # include # include # include @@ -27,6 +28,13 @@ int Architecture::emit(ostream&out, Entity*entity) { int errors = 0; + + for (map::iterator cur = signals_.begin() + ; cur != signals_.end() ; ++cur) { + + errors += cur->second->emit(out, entity, this); + } + for (list::iterator cur = statements_.begin() ; cur != statements_.end() ; ++cur) { @@ -52,7 +60,9 @@ int SignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc) Expression*rval = rval_.front(); out << "// " << get_fileline() << endl; - out << "assign " << target_name_ << " = "; + out << "assign "; + errors += lval_->emit(out, ent, arc); + out << " = "; errors += rval->emit(out, ent, arc); diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index c9afc9052..5bcdb4cca 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -127,7 +127,8 @@ void Signal::dump(ostream&out) const void SignalAssignment::dump(ostream&out) const { out << " SignalAssignment file=" << get_fileline() << endl; - out << " " << target_name_ << " <= ..." << endl; + lval_->dump(out, 4); + out << " <= ..." << endl; for (list::const_iterator cur = rval_.begin() ; cur != rval_.end() ; ++cur) { @@ -218,6 +219,8 @@ void ExpName::dump(ostream&out, int indent) const { out << setw(indent) << "" << "ExpName(\"" << name_ << "\")" << " at " << get_fileline() << endl; + if (index_) + index_->dump(out, indent+6); } void ExpUAbs::dump(ostream&out, int indent) const diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 10ddf2317..691d6f008 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -24,11 +24,11 @@ # include # include "StringHeap.h" # include "LineInfo.h" +# include "vtype.h" typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t; class Architecture; -class VType; class InterfacePort : public LineInfo { public: @@ -99,13 +99,7 @@ class Entity : public ComponentBase { std::maparch_; Architecture*bind_arch_; - enum vtype_t { VNONE, VBOOL, VLOGIC }; - struct decl_t { - bool signed_flag; - vtype_t type; - long msb, lsb; - }; - map declarations_; + map declarations_; int elaborate_ports_(void); }; diff --git a/vhdlpp/entity_elaborate.cc b/vhdlpp/entity_elaborate.cc index 47e38fcac..d79347b8c 100644 --- a/vhdlpp/entity_elaborate.cc +++ b/vhdlpp/entity_elaborate.cc @@ -78,6 +78,9 @@ int Entity::elaborate() << "." << endl; errors += elaborate_ports_(); + + errors += bind_arch_->elaborate(this); + return errors; } @@ -90,11 +93,7 @@ int Entity::elaborate_ports_(void) ; cur != ports.end() ; ++cur) { InterfacePort*cur_port = *cur; - decl_t cur_decl; - cur_decl.type = VNONE; - cur_decl.signed_flag = false; - cur_decl.msb = 0; - cur_decl.lsb = 0; + VType::decl_t cur_decl; const VType*type = cur_port->type; if (type == 0) { @@ -105,50 +104,7 @@ int Entity::elaborate_ports_(void) continue; } - if (const VTypePrimitive*use_type = dynamic_cast(type)) { - switch (use_type->type()) { - case VTypePrimitive::BOOLEAN: - case VTypePrimitive::BIT: - cur_decl.type = VBOOL; - break; - case VTypePrimitive::STDLOGIC: - cur_decl.type = VLOGIC; - break; - case VTypePrimitive::INTEGER: - cur_decl.type = VBOOL; - cur_decl.msb = 31; - cur_decl.lsb = 0; - break; - } - - } else if (const VTypeArray*arr_type = dynamic_cast(type)) { - const VTypePrimitive*base = dynamic_cast(arr_type->element_type()); - assert(base != 0); - - switch (base->type()) { - case VTypePrimitive::BOOLEAN: - case VTypePrimitive::BIT: - cur_decl.type = VBOOL; - break; - case VTypePrimitive::STDLOGIC: - cur_decl.type = VLOGIC; - break; - case VTypePrimitive::INTEGER: - cur_decl.type = VLOGIC; - assert(0); - break; - } - - cur_decl.msb = arr_type->dimension(0).msb(); - cur_decl.lsb = arr_type->dimension(0).lsb(); - cur_decl.signed_flag = arr_type->signed_vector(); - - } else { - cerr << get_fileline() << ": error: " - << "I don't know how to map port " << cur_port->name - << " type " << typeid(*cur_port->type).name() << "." << endl; - errors += 1; - } + type->elaborate(cur_decl); declarations_[cur_port->name] = cur_decl; } diff --git a/vhdlpp/entity_emit.cc b/vhdlpp/entity_emit.cc index 236d92c3f..2f6faa19f 100644 --- a/vhdlpp/entity_emit.cc +++ b/vhdlpp/entity_emit.cc @@ -51,7 +51,7 @@ int Entity::emit(ostream&out) ; cur != ports.end() ; ++cur) { InterfacePort*port = *cur; - decl_t&decl = declarations_[port->name]; + VType::decl_t&decl = declarations_[port->name]; if (sep) out << sep; else sep = ", "; @@ -81,32 +81,10 @@ int Entity::emit(ostream&out) out << ";" << endl; - for (map::const_iterator cur = declarations_.begin() + for (map::const_iterator cur = declarations_.begin() ; cur != declarations_.end() ; ++cur) { - switch (cur->second.type) { - case VNONE: - out << "// N type for " << cur->first << endl; - break; - case VLOGIC: - out << "wire logic "; - if (cur->second.signed_flag) - out << "signed "; - if (cur->second.msb != cur->second.lsb) - out << "[" << cur->second.msb - << ":" << cur->second.lsb << "] "; - out << cur->first << ";" << endl; - break; - case VBOOL: - out << "wire bool "; - if (cur->second.signed_flag) - out << "signed "; - if (cur->second.msb != cur->second.lsb) - out << "[" << cur->second.msb - << ":" << cur->second.lsb << "] "; - out << cur->first << ";" << endl; - break; - } + cur->second.emit(out, cur->first); } errors += bind_arch_->emit(out, this); diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 823b52fff..a5c583912 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -87,12 +87,18 @@ ExpLogical::~ExpLogical() } ExpName::ExpName(perm_string nn) -: name_(nn) +: name_(nn), index_(0) +{ +} + +ExpName::ExpName(perm_string nn, Expression*ix) +: name_(nn), index_(ix) { } ExpName::~ExpName() { + delete index_; } ExpUAbs::ExpUAbs(Expression*op1) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index ec540acd0..b62497c05 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -156,14 +156,17 @@ class ExpName : public Expression { public: ExpName(perm_string nn); + ExpName(perm_string nn, Expression*index); ~ExpName(); + public: // Base methods int emit(ostream&out, Entity*ent, Architecture*arc); bool is_primary(void) const; void dump(ostream&out, int indent) const; private: perm_string name_; + Expression*index_; }; class ExpUAbs : public ExpUnary { diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 9555a0941..eb6154538 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -141,11 +141,17 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } -int ExpName::emit(ostream&out, Entity*, Architecture*) +int ExpName::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; out << name_; + if (index_) { + out << "["; + errors += index_->emit(out, ent, arc); + out << "]"; + } + return errors; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 5d0148e26..b9bd14f59 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -32,6 +32,7 @@ # include # include # include +# include inline void FILE_NAME(LineInfo*tmp, const struct yyltype&where) { @@ -129,7 +130,6 @@ static map block_components; %type direction -%type name %type interface_element interface_list entity_header %type port_clause port_clause_opt %type mode @@ -140,6 +140,7 @@ static map block_components; %type expression factor primary relation %type expression_logical expression_logical_and expression_logical_or %type expression_logical_xnor expression_logical_xor +%type name %type shift_expression simple_expression term waveform_element %type waveform waveform_elements @@ -345,16 +346,17 @@ configuration_declaration concurrent_signal_assignment_statement : name LEQ waveform ';' - { perm_string targ_name = lex_strings.make($1); - SignalAssignment*tmp = new SignalAssignment(targ_name, *$3); + { ExpName*name = dynamic_cast ($1); + assert(name); + SignalAssignment*tmp = new SignalAssignment(name, *$3); FILE_NAME(tmp, @1); $$ = tmp; - delete[]$1; delete $3; } | name LEQ error ';' { errormsg(@2, "Syntax error in signal assignment waveform.\n"); + delete $1; $$ = 0; yyerrok; } @@ -695,10 +697,16 @@ mode name : IDENTIFIER - { $$ = $1; } + { ExpName*tmp = new ExpName(lex_strings.make($1)); + FILE_NAME(tmp, @1); + delete[]$1; + $$ = tmp; + } | IDENTIFIER '(' expression ')' - { sorrymsg(@3, "Indexed names not supported yet.\n"); - $$ = $1; + { ExpName*tmp = new ExpName(lex_strings.make($1), $3); + FILE_NAME(tmp, @1); + delete[]$1; + $$ = tmp; } ; @@ -785,11 +793,7 @@ port_map_aspect_opt primary : name - { ExpName*tmp = new ExpName(lex_strings.make($1)); - FILE_NAME(tmp, @1); - delete[]$1; - $$ = tmp; - } + { $$ = $1; } | INT_LITERAL { ExpInteger*tmp = new ExpInteger($1); FILE_NAME(tmp, @1); diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index 0b869b398..b0c014884 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -18,6 +18,10 @@ */ # include "vsignal.h" +# include "vtype.h" +# include + +using namespace std; Signal::Signal(perm_string nam, const VType*typ) : name_(nam), type_(typ) @@ -27,3 +31,13 @@ Signal::Signal(perm_string nam, const VType*typ) Signal::~Signal() { } + +int Signal::emit(ostream&out, Entity*, Architecture*) +{ + int errors = 0; + + VType::decl_t decl; + type_->elaborate(decl); + errors += decl.emit(out, name_); + return errors; +} diff --git a/vhdlpp/vsignal.h b/vhdlpp/vsignal.h index dca6eca3d..32109e500 100644 --- a/vhdlpp/vsignal.h +++ b/vhdlpp/vsignal.h @@ -22,6 +22,8 @@ # include "StringHeap.h" # include "LineInfo.h" +class Architecture; +class Entity; class VType; class Signal : public LineInfo { @@ -30,6 +32,8 @@ class Signal : public LineInfo { Signal(perm_string name, const VType*type); ~Signal(); + int emit(ostream&out, Entity*ent, Architecture*arc); + void dump(ostream&out) const; private: diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 4a2984785..de000fb74 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -37,6 +37,19 @@ class VType { virtual ~VType() =0; virtual void show(std::ostream&) const; + + public: + enum vtype_t { VNONE, VBOOL, VLOGIC }; + struct decl_t { + public: + decl_t() : signed_flag(false), type(VNONE), msb(0), lsb(0) { } + int emit(std::ostream&out, perm_string name) const; + public: + bool signed_flag; + vtype_t type; + long msb, lsb; + }; + virtual void elaborate(decl_t&decl) const =0; }; inline std::ostream&operator << (std::ostream&out, const VType&item) @@ -71,6 +84,7 @@ class VTypePrimitive : public VType { ~VTypePrimitive(); void show(std::ostream&) const; + void elaborate(decl_t&decl) const; type_t type() const { return type_; } @@ -112,6 +126,7 @@ class VTypeArray : public VType { ~VTypeArray(); void show(std::ostream&) const; + void elaborate(decl_t&decl) const; size_t dimensions() const; const range_t&dimension(size_t idx) const diff --git a/vhdlpp/vtype_elaborate.cc b/vhdlpp/vtype_elaborate.cc new file mode 100644 index 000000000..b396cc034 --- /dev/null +++ b/vhdlpp/vtype_elaborate.cc @@ -0,0 +1,60 @@ +/* + * 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 +# include + +using namespace std; + +void VTypeArray::elaborate(VType::decl_t&decl) const +{ + const VTypePrimitive*base = dynamic_cast(etype_); + assert(base != 0); + + base->elaborate(decl); + //assert(decl.msb == decl.lsb == 0); + + decl.msb = dimension(0).msb(); + decl.lsb = dimension(0).lsb(); + decl.signed_flag = signed_flag_; +} + +void VTypePrimitive::elaborate(VType::decl_t&decl) const +{ + decl.type = VNONE; + decl.signed_flag = false; + decl.msb = 0; + decl.lsb = 0; + + switch (type_) { + case BOOLEAN: + case BIT: + decl.type = VBOOL; + break; + case STDLOGIC: + decl.type = VLOGIC; + break; + case INTEGER: + decl.type = VBOOL; + decl.msb = 31; + decl.lsb = 0; + break; + } +} diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc new file mode 100644 index 000000000..981e08bdd --- /dev/null +++ b/vhdlpp/vtype_emit.cc @@ -0,0 +1,53 @@ +/* + * 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 +# include +# include + +using namespace std; + +int VType::decl_t::emit(ostream&out, perm_string name) const +{ + switch (type) { + case VType::VNONE: + out << "// N type for " << name << endl; + break; + case VType::VLOGIC: + out << "wire logic "; + if (signed_flag) + out << "signed "; + if (msb != lsb) + out << "[" << msb << ":" << lsb << "] "; + out << name << ";" << endl; + break; + case VType::VBOOL: + out << "wire bool "; + if (signed_flag) + out << "signed "; + if (msb != lsb) + out << "[" << msb << ":" << lsb << "] "; + out << name << ";" << endl; + break; + } + + return 0; +}