Arrange for ports used as l-values to be declared as "reg".

Entity output ports may be used as l-values in a process within
the bound architecture. Detect that case during elaboration and
adjust the signal declaration so that it works in the Verilog pass.
This commit is contained in:
Stephen Williams 2011-05-15 16:17:51 -07:00
parent fc25ccde06
commit a53082176d
13 changed files with 179 additions and 7 deletions

View File

@ -59,8 +59,10 @@ LIBS = @LIBS@ @EXTRALIBS@
M = StringHeap.o LineInfo.o
O = main.o architec.o architec_elaborate.o compiler.o entity.o entity_elaborate.o \
expression.o package.o scope.o sequential.o vsignal.o vtype.o vtype_elaborate.o \
O = main.o architec.o compiler.o entity.o \
expression.o package.o scope.o sequential.o vsignal.o vtype.o \
architec_elaborate.o entity_elaborate.o expression_elaborate.o \
sequential_elaborate.o vtype_elaborate.o \
lexor.o lexor_keyword.o parse.o \
parse_misc.o library.o vhdlreal.o vhdlint.o \
architec_emit.o entity_emit.o expression_emit.o sequential_emit.o vtype_emit.o \

View File

@ -20,6 +20,7 @@
# include "architec.h"
# include "entity.h"
# include "expression.h"
# include "sequential.h"
# include <typeinfo>
# include <cassert>
@ -45,7 +46,7 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
{
int errors = 0;
const ComponentBase*base = arc->find_component(cname_);
ComponentBase*base = arc->find_component(cname_);
if (base == 0) {
cerr << get_fileline() << ": error: No component declaration"
<< " for instance " << iname_
@ -71,5 +72,12 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
int ProcessStatement::elaborate(Entity*ent, Architecture*arc)
{
return 0;
int errors = 0;
for (list<SequentialStmt*>::iterator cur = statements_list_.begin()
; cur != statements_list_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc);
}
return errors;
}

View File

@ -20,6 +20,7 @@
# include "entity.h"
# include "architec.h"
# include <cassert>
using namespace std;
@ -69,3 +70,10 @@ Architecture* Entity::add_architecture(Architecture*that)
return arch_[that->get_name()] = that;
}
void Entity::set_declaration_l_value(perm_string nam, bool flag)
{
map<perm_string,VType::decl_t>::iterator cur = declarations_.find(nam);
assert(cur != declarations_.end());
cur->second.reg_flag = flag;
}

View File

@ -33,6 +33,8 @@ class Architecture;
class InterfacePort : public LineInfo {
public:
InterfacePort() { mode = PORT_NONE; type=0; }
// Port direction from the source code.
port_mode_t mode;
// Name of the port from the source code
@ -92,7 +94,17 @@ class Entity : public ComponentBase {
// returned pointer is the same as the passed pointer.
Architecture* add_architecture(Architecture*);
// After the architecture is bound, elaboration calls this
// method to elaborate this entity. This method arranges for
// elaboration to hapen all the way through the architecture
// that is bound to this entity.
int elaborate();
// During elaboration, it may be discovered that a port is
// used as an l-value in an assignment. This method tweaks the
// declaration to allow for that case.
void set_declaration_l_value(perm_string by_name, bool flag);
int emit(ostream&out);
void dump(ostream&out, int indent = 0) const;

View File

@ -69,6 +69,8 @@ int Entity::emit(ostream&out)
break;
case PORT_OUT:
out << "output ";
if (decl.reg_flag)
out << "reg ";
if (decl.msb != decl.lsb)
out << "[" << decl.msb
<< ":" << decl.lsb << "] ";

View File

@ -40,6 +40,13 @@ class Expression : public LineInfo {
Expression();
virtual ~Expression() =0;
// This virtual method handles the special case of elaborating
// an expression that is the l-value of a sequential variable
// assignment. This generates an error for most cases, but
// expressions that are valid l-values return 0 and set any
// flags needed to indicate their status as writable variables.
virtual int elaborate_lval(Entity*ent, Architecture*arc);
// The emit virtual method is called by architecture emit to
// output the generated code for the expression. The derived
// class fills in the details of what exactly happened.
@ -196,6 +203,7 @@ class ExpName : public Expression {
~ExpName();
public: // Base methods
int elaborate_lval(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*ent, Architecture*arc);
bool is_primary(void) const;
bool evaluate(ScopeBase*scope, int64_t&val) const;
@ -213,6 +221,7 @@ class ExpNameALL : public ExpName {
ExpNameALL() : ExpName(perm_string()) { }
public:
int elaborate_lval(Entity*ent, Architecture*arc);
void dump(ostream&out, int indent =0) const;
};

View File

@ -0,0 +1,62 @@
/*
* 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
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
*/
# include "expression.h"
# include "architec.h"
# include "entity.h"
# include <iostream>
using namespace std;
int Expression::elaborate_lval(Entity*, Architecture*)
{
cerr << get_fileline() << ": error: Expression is not a valie l-value." << endl;
return 1;
}
int ExpName::elaborate_lval(Entity*ent, Architecture*arc)
{
int errors = 0;
if (const InterfacePort*cur = ent->find_port(name_)) {
if (cur->mode != PORT_OUT) {
cerr << get_fileline() << ": error: Assignment to "
"input port " << name_ << "." << endl;
return errors += 1;
}
ent->set_declaration_l_value(name_, true);
return errors;
}
Signal*sig = arc->find_signal(name_);
if (sig == 0) {
cerr << get_fileline() << ": error: Signal/variable " << name_
<< " not found in this context." << endl;
return errors + 1;
}
return errors;
}
int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc)
{
return Expression::elaborate_lval(ent, arc);
}

View File

@ -93,3 +93,12 @@ ComponentBase* Scope::find_component(perm_string by_name)
else
return cur->second;
}
Signal* Scope::find_signal(perm_string by_name)
{
map<perm_string,Signal*>::const_iterator cur = signals_.find(by_name);
if (cur == signals_.end())
return 0;
else
return cur->second;
}

View File

@ -64,6 +64,8 @@ class Scope : public ScopeBase {
ComponentBase* find_component(perm_string by_name);
Signal* find_signal(perm_string by_name);
public:
void dump_scope(ostream&out) const;

View File

@ -33,6 +33,7 @@ class SequentialStmt : public LineInfo {
virtual ~SequentialStmt() =0;
public:
virtual int elaborate(Entity*ent, Architecture*arc);
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
virtual void dump(ostream&out, int indent) const;
};
@ -45,6 +46,7 @@ class IfSequential : public SequentialStmt {
~IfSequential();
public:
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
void dump(ostream&out, int indent) const;
@ -60,6 +62,7 @@ class SignalSeqAssignment : public SequentialStmt {
~SignalSeqAssignment();
public:
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
void dump(ostream&out, int indent) const;

View File

@ -0,0 +1,52 @@
/*
* 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 "sequential.h"
# include "expression.h"
int SequentialStmt::elaborate(Entity*, Architecture*)
{
return 0;
}
int IfSequential::elaborate(Entity*ent, Architecture*arc)
{
int errors = 0;
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc);
}
for (list<SequentialStmt*>::iterator cur = else_.begin()
; cur != else_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc);
}
return errors;
}
int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc)
{
int errors = 0;
errors += lval_->elaborate_lval(ent, arc);
return errors;
}

View File

@ -42,9 +42,10 @@ class VType {
enum vtype_t { VNONE, VBOOL, VLOGIC };
struct decl_t {
public:
decl_t() : signed_flag(false), type(VNONE), msb(0), lsb(0) { }
decl_t() : reg_flag(false), signed_flag(false), type(VNONE), msb(0), lsb(0) { }
int emit(std::ostream&out, perm_string name) const;
public:
bool reg_flag;
bool signed_flag;
vtype_t type;
long msb, lsb;

View File

@ -27,12 +27,14 @@ using namespace std;
int VType::decl_t::emit(ostream&out, perm_string name) const
{
const char*wire = reg_flag? "reg" : "wire";
switch (type) {
case VType::VNONE:
out << "// N type for " << name << endl;
break;
case VType::VLOGIC:
out << "wire logic ";
out << wire<< " logic ";
if (signed_flag)
out << "signed ";
if (msb != lsb)
@ -40,7 +42,7 @@ int VType::decl_t::emit(ostream&out, perm_string name) const
out << name << ";" << endl;
break;
case VType::VBOOL:
out << "wire bool ";
out << wire << " bool ";
if (signed_flag)
out << "signed ";
if (msb != lsb)