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