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
|
||||
|
||||
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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 << "] ";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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);
|
||||
|
||||
Signal* find_signal(perm_string by_name);
|
||||
|
||||
public:
|
||||
void dump_scope(ostream&out) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue