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.
This commit is contained in:
Stephen Williams 2011-03-27 12:01:58 -07:00
parent f057ce0859
commit 162b26c101
18 changed files with 245 additions and 105 deletions

View File

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

View File

@ -44,8 +44,8 @@ Architecture::Statement::~Statement()
{
}
SignalAssignment::SignalAssignment(perm_string targ_name, list<Expression*>&rv)
: target_name_(targ_name)
SignalAssignment::SignalAssignment(ExpName*name, list<Expression*>&rv)
: lval_(name)
{
rval_.splice(rval_.end(), rv);
}

View File

@ -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<Expression*>&rval);
SignalAssignment(ExpName*target, std::list<Expression*>&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<Expression*> rval_;
};

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "architec.h"
# include "entity.h"
# include "expression.h"
# include <typeinfo>
# include <cassert>
int Architecture::elaborate(Entity*entity)
{
return 0;
}

View File

@ -20,6 +20,7 @@
# include "architec.h"
# include "entity.h"
# include "expression.h"
# include "vsignal.h"
# include <iostream>
# include <typeinfo>
# include <cassert>
@ -27,6 +28,13 @@
int Architecture::emit(ostream&out, Entity*entity)
{
int errors = 0;
for (map<perm_string,Signal*>::iterator cur = signals_.begin()
; cur != signals_.end() ; ++cur) {
errors += cur->second->emit(out, entity, this);
}
for (list<Architecture::Statement*>::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);

View File

@ -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_ << " <= <expr>..." << endl;
lval_->dump(out, 4);
out << " <= <expr>..." << endl;
for (list<Expression*>::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

View File

@ -24,11 +24,11 @@
# include <vector>
# 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::map<perm_string,Architecture*>arch_;
Architecture*bind_arch_;
enum vtype_t { VNONE, VBOOL, VLOGIC };
struct decl_t {
bool signed_flag;
vtype_t type;
long msb, lsb;
};
map<perm_string,decl_t> declarations_;
map<perm_string,VType::decl_t> declarations_;
int elaborate_ports_(void);
};

View File

@ -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<const VTypePrimitive*>(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<const VTypeArray*>(type)) {
const VTypePrimitive*base = dynamic_cast<const VTypePrimitive*>(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;
}

View File

@ -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<perm_string,decl_t>::const_iterator cur = declarations_.begin()
for (map<perm_string,VType::decl_t>::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);

View File

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

View File

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

View File

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

View File

@ -32,6 +32,7 @@
# include <cstdarg>
# include <list>
# include <map>
# include <assert.h>
inline void FILE_NAME(LineInfo*tmp, const struct yyltype&where)
{
@ -129,7 +130,6 @@ static map<perm_string, ComponentBase*> block_components;
%type <flag> direction
%type <text> name
%type <interface_list> interface_element interface_list entity_header
%type <interface_list> port_clause port_clause_opt
%type <port_mode> mode
@ -140,6 +140,7 @@ static map<perm_string, ComponentBase*> block_components;
%type <expr> expression factor primary relation
%type <expr> expression_logical expression_logical_and expression_logical_or
%type <expr> expression_logical_xnor expression_logical_xor
%type <expr> name
%type <expr> shift_expression simple_expression term waveform_element
%type <expr_list> 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<ExpName*> ($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);

View File

@ -18,6 +18,10 @@
*/
# include "vsignal.h"
# include "vtype.h"
# include <iostream>
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;
}

View File

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

View File

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

60
vhdlpp/vtype_elaborate.cc Normal file
View File

@ -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 <typeinfo>
# include <cassert>
using namespace std;
void VTypeArray::elaborate(VType::decl_t&decl) const
{
const VTypePrimitive*base = dynamic_cast<const VTypePrimitive*>(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;
}
}

53
vhdlpp/vtype_emit.cc Normal file
View File

@ -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 <iostream>
# include <typeinfo>
# include <cassert>
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;
}