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:
parent
fc25ccde06
commit
a53082176d
|
|
@ -59,8 +59,10 @@ LIBS = @LIBS@ @EXTRALIBS@
|
||||||
|
|
||||||
M = StringHeap.o LineInfo.o
|
M = StringHeap.o LineInfo.o
|
||||||
|
|
||||||
O = main.o architec.o architec_elaborate.o compiler.o entity.o entity_elaborate.o \
|
O = main.o architec.o compiler.o entity.o \
|
||||||
expression.o package.o scope.o sequential.o vsignal.o vtype.o vtype_elaborate.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 \
|
lexor.o lexor_keyword.o parse.o \
|
||||||
parse_misc.o library.o vhdlreal.o vhdlint.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 \
|
architec_emit.o entity_emit.o expression_emit.o sequential_emit.o vtype_emit.o \
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
# include "architec.h"
|
# include "architec.h"
|
||||||
# include "entity.h"
|
# include "entity.h"
|
||||||
# include "expression.h"
|
# include "expression.h"
|
||||||
|
# include "sequential.h"
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
|
||||||
|
|
@ -45,7 +46,7 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
const ComponentBase*base = arc->find_component(cname_);
|
ComponentBase*base = arc->find_component(cname_);
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
cerr << get_fileline() << ": error: No component declaration"
|
cerr << get_fileline() << ": error: No component declaration"
|
||||||
<< " for instance " << iname_
|
<< " for instance " << iname_
|
||||||
|
|
@ -71,5 +72,12 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
|
||||||
|
|
||||||
int ProcessStatement::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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
# include "entity.h"
|
# include "entity.h"
|
||||||
# include "architec.h"
|
# include "architec.h"
|
||||||
|
# include <cassert>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
@ -69,3 +70,10 @@ Architecture* Entity::add_architecture(Architecture*that)
|
||||||
|
|
||||||
return arch_[that->get_name()] = 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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ class Architecture;
|
||||||
|
|
||||||
class InterfacePort : public LineInfo {
|
class InterfacePort : public LineInfo {
|
||||||
public:
|
public:
|
||||||
|
InterfacePort() { mode = PORT_NONE; type=0; }
|
||||||
|
|
||||||
// Port direction from the source code.
|
// Port direction from the source code.
|
||||||
port_mode_t mode;
|
port_mode_t mode;
|
||||||
// Name of the port from the source code
|
// 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.
|
// returned pointer is the same as the passed pointer.
|
||||||
Architecture* add_architecture(Architecture*);
|
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();
|
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);
|
int emit(ostream&out);
|
||||||
|
|
||||||
void dump(ostream&out, int indent = 0) const;
|
void dump(ostream&out, int indent = 0) const;
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,8 @@ int Entity::emit(ostream&out)
|
||||||
break;
|
break;
|
||||||
case PORT_OUT:
|
case PORT_OUT:
|
||||||
out << "output ";
|
out << "output ";
|
||||||
|
if (decl.reg_flag)
|
||||||
|
out << "reg ";
|
||||||
if (decl.msb != decl.lsb)
|
if (decl.msb != decl.lsb)
|
||||||
out << "[" << decl.msb
|
out << "[" << decl.msb
|
||||||
<< ":" << decl.lsb << "] ";
|
<< ":" << decl.lsb << "] ";
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,13 @@ class Expression : public LineInfo {
|
||||||
Expression();
|
Expression();
|
||||||
virtual ~Expression() =0;
|
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
|
// The emit virtual method is called by architecture emit to
|
||||||
// output the generated code for the expression. The derived
|
// output the generated code for the expression. The derived
|
||||||
// class fills in the details of what exactly happened.
|
// class fills in the details of what exactly happened.
|
||||||
|
|
@ -196,6 +203,7 @@ class ExpName : public Expression {
|
||||||
~ExpName();
|
~ExpName();
|
||||||
|
|
||||||
public: // Base methods
|
public: // Base methods
|
||||||
|
int elaborate_lval(Entity*ent, Architecture*arc);
|
||||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||||
bool is_primary(void) const;
|
bool is_primary(void) const;
|
||||||
bool evaluate(ScopeBase*scope, int64_t&val) const;
|
bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||||
|
|
@ -213,6 +221,7 @@ class ExpNameALL : public ExpName {
|
||||||
ExpNameALL() : ExpName(perm_string()) { }
|
ExpNameALL() : ExpName(perm_string()) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int elaborate_lval(Entity*ent, Architecture*arc);
|
||||||
void dump(ostream&out, int indent =0) const;
|
void dump(ostream&out, int indent =0) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -93,3 +93,12 @@ ComponentBase* Scope::find_component(perm_string by_name)
|
||||||
else
|
else
|
||||||
return cur->second;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ class Scope : public ScopeBase {
|
||||||
|
|
||||||
ComponentBase* find_component(perm_string by_name);
|
ComponentBase* find_component(perm_string by_name);
|
||||||
|
|
||||||
|
Signal* find_signal(perm_string by_name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void dump_scope(ostream&out) const;
|
void dump_scope(ostream&out) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ class SequentialStmt : public LineInfo {
|
||||||
virtual ~SequentialStmt() =0;
|
virtual ~SequentialStmt() =0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual int elaborate(Entity*ent, Architecture*arc);
|
||||||
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
|
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||||
virtual void dump(ostream&out, int indent) const;
|
virtual void dump(ostream&out, int indent) const;
|
||||||
};
|
};
|
||||||
|
|
@ -45,6 +46,7 @@ class IfSequential : public SequentialStmt {
|
||||||
~IfSequential();
|
~IfSequential();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int elaborate(Entity*ent, Architecture*arc);
|
||||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||||
void dump(ostream&out, int indent) const;
|
void dump(ostream&out, int indent) const;
|
||||||
|
|
||||||
|
|
@ -60,6 +62,7 @@ class SignalSeqAssignment : public SequentialStmt {
|
||||||
~SignalSeqAssignment();
|
~SignalSeqAssignment();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int elaborate(Entity*ent, Architecture*arc);
|
||||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||||
void dump(ostream&out, int indent) const;
|
void dump(ostream&out, int indent) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -42,9 +42,10 @@ class VType {
|
||||||
enum vtype_t { VNONE, VBOOL, VLOGIC };
|
enum vtype_t { VNONE, VBOOL, VLOGIC };
|
||||||
struct decl_t {
|
struct decl_t {
|
||||||
public:
|
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;
|
int emit(std::ostream&out, perm_string name) const;
|
||||||
public:
|
public:
|
||||||
|
bool reg_flag;
|
||||||
bool signed_flag;
|
bool signed_flag;
|
||||||
vtype_t type;
|
vtype_t type;
|
||||||
long msb, lsb;
|
long msb, lsb;
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,14 @@ using namespace std;
|
||||||
|
|
||||||
int VType::decl_t::emit(ostream&out, perm_string name) const
|
int VType::decl_t::emit(ostream&out, perm_string name) const
|
||||||
{
|
{
|
||||||
|
const char*wire = reg_flag? "reg" : "wire";
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case VType::VNONE:
|
case VType::VNONE:
|
||||||
out << "// N type for " << name << endl;
|
out << "// N type for " << name << endl;
|
||||||
break;
|
break;
|
||||||
case VType::VLOGIC:
|
case VType::VLOGIC:
|
||||||
out << "wire logic ";
|
out << wire<< " logic ";
|
||||||
if (signed_flag)
|
if (signed_flag)
|
||||||
out << "signed ";
|
out << "signed ";
|
||||||
if (msb != lsb)
|
if (msb != lsb)
|
||||||
|
|
@ -40,7 +42,7 @@ int VType::decl_t::emit(ostream&out, perm_string name) const
|
||||||
out << name << ";" << endl;
|
out << name << ";" << endl;
|
||||||
break;
|
break;
|
||||||
case VType::VBOOL:
|
case VType::VBOOL:
|
||||||
out << "wire bool ";
|
out << wire << " bool ";
|
||||||
if (signed_flag)
|
if (signed_flag)
|
||||||
out << "signed ";
|
out << "signed ";
|
||||||
if (msb != lsb)
|
if (msb != lsb)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue