2011-01-31 20:16:14 +01:00
|
|
|
/*
|
|
|
|
|
* 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"
|
2011-05-15 20:07:42 +02:00
|
|
|
# include "sequential.h"
|
2011-03-27 21:01:58 +02:00
|
|
|
# include "vsignal.h"
|
2011-01-31 20:16:14 +01:00
|
|
|
# include <iostream>
|
|
|
|
|
# include <typeinfo>
|
|
|
|
|
# include <cassert>
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc)
|
2011-01-31 20:16:14 +01:00
|
|
|
{
|
|
|
|
|
int errors = 0;
|
2011-03-27 21:01:58 +02:00
|
|
|
|
Use separate containers for current and previous scopes
This patch introduces in ScopeBase separate containers
for declarations coming from the current scope and from
the previous scopes.
Until now, in one scope, all objects were kept in an stl map.
When a scope was created inside other scopes, a shallow
copy of the map was made. This solution was nice for
name shadowing (in new scopes, when a name was
encountered, the old objects were overridden by a new
one), but didn't allow for distinguishing where the objects
were allocated. As a result, it is impossible to know who
the owner is and who should delete them.
In this commit ScopeBase gets two containers: for old
and new objects. If a ScopeBase is made from another
ScopeBase object, all objects from the copied object
go to an old_XXX container, where XXX depends on the
type of the copied objects. When a ScopeBase object
is deleted, the objects from new_XXX are deleted and
the ones from old_XXX are not touched.
This patch adds some complexity to the internals
of ScopeBase, but leaves its interface unchanged.
2011-07-20 16:34:36 +02:00
|
|
|
for (map<perm_string,Signal*>::iterator cur = old_signals_.begin()
|
|
|
|
|
; cur != old_signals_.end() ; ++cur) {
|
2011-03-27 21:01:58 +02:00
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
errors += cur->second->emit(out, entity, arc);
|
|
|
|
|
}
|
Use separate containers for current and previous scopes
This patch introduces in ScopeBase separate containers
for declarations coming from the current scope and from
the previous scopes.
Until now, in one scope, all objects were kept in an stl map.
When a scope was created inside other scopes, a shallow
copy of the map was made. This solution was nice for
name shadowing (in new scopes, when a name was
encountered, the old objects were overridden by a new
one), but didn't allow for distinguishing where the objects
were allocated. As a result, it is impossible to know who
the owner is and who should delete them.
In this commit ScopeBase gets two containers: for old
and new objects. If a ScopeBase is made from another
ScopeBase object, all objects from the copied object
go to an old_XXX container, where XXX depends on the
type of the copied objects. When a ScopeBase object
is deleted, the objects from new_XXX are deleted and
the ones from old_XXX are not touched.
This patch adds some complexity to the internals
of ScopeBase, but leaves its interface unchanged.
2011-07-20 16:34:36 +02:00
|
|
|
for (map<perm_string,Signal*>::iterator cur = new_signals_.begin()
|
|
|
|
|
; cur != new_signals_.end() ; ++cur) {
|
2011-04-18 02:19:09 +02:00
|
|
|
|
Use separate containers for current and previous scopes
This patch introduces in ScopeBase separate containers
for declarations coming from the current scope and from
the previous scopes.
Until now, in one scope, all objects were kept in an stl map.
When a scope was created inside other scopes, a shallow
copy of the map was made. This solution was nice for
name shadowing (in new scopes, when a name was
encountered, the old objects were overridden by a new
one), but didn't allow for distinguishing where the objects
were allocated. As a result, it is impossible to know who
the owner is and who should delete them.
In this commit ScopeBase gets two containers: for old
and new objects. If a ScopeBase is made from another
ScopeBase object, all objects from the copied object
go to an old_XXX container, where XXX depends on the
type of the copied objects. When a ScopeBase object
is deleted, the objects from new_XXX are deleted and
the ones from old_XXX are not touched.
This patch adds some complexity to the internals
of ScopeBase, but leaves its interface unchanged.
2011-07-20 16:34:36 +02:00
|
|
|
errors += cur->second->emit(out, entity, arc);
|
|
|
|
|
}
|
2011-04-18 02:19:09 +02:00
|
|
|
return errors;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-18 05:19:15 +02:00
|
|
|
int Scope::emit_variables(ostream&out, Entity*entity, Architecture*arc)
|
|
|
|
|
{
|
|
|
|
|
int errors = 0;
|
|
|
|
|
|
|
|
|
|
for (map<perm_string,Variable*>::iterator cur = old_variables_.begin()
|
|
|
|
|
; cur != old_variables_.end() ; ++cur) {
|
|
|
|
|
|
|
|
|
|
errors += cur->second->emit(out, entity, arc);
|
|
|
|
|
}
|
|
|
|
|
for (map<perm_string,Variable*>::iterator cur = new_variables_.begin()
|
|
|
|
|
; cur != new_variables_.end() ; ++cur) {
|
|
|
|
|
|
|
|
|
|
errors += cur->second->emit(out, entity, arc);
|
|
|
|
|
}
|
|
|
|
|
return errors;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
int Architecture::emit(ostream&out, Entity*entity)
|
|
|
|
|
{
|
|
|
|
|
int errors = 0;
|
|
|
|
|
|
Use separate containers for current and previous scopes
This patch introduces in ScopeBase separate containers
for declarations coming from the current scope and from
the previous scopes.
Until now, in one scope, all objects were kept in an stl map.
When a scope was created inside other scopes, a shallow
copy of the map was made. This solution was nice for
name shadowing (in new scopes, when a name was
encountered, the old objects were overridden by a new
one), but didn't allow for distinguishing where the objects
were allocated. As a result, it is impossible to know who
the owner is and who should delete them.
In this commit ScopeBase gets two containers: for old
and new objects. If a ScopeBase is made from another
ScopeBase object, all objects from the copied object
go to an old_XXX container, where XXX depends on the
type of the copied objects. When a ScopeBase object
is deleted, the objects from new_XXX are deleted and
the ones from old_XXX are not touched.
This patch adds some complexity to the internals
of ScopeBase, but leaves its interface unchanged.
2011-07-20 16:34:36 +02:00
|
|
|
for (map<perm_string,struct const_t*>::iterator cur = old_constants_.begin()
|
|
|
|
|
; cur != old_constants_.end() ; ++cur) {
|
|
|
|
|
|
|
|
|
|
out << "localparam " << cur->first << " = ";
|
|
|
|
|
errors += cur->second->val->emit(out, entity, this);
|
|
|
|
|
out << ";" << endl;
|
|
|
|
|
}
|
|
|
|
|
for (map<perm_string,struct const_t*>::iterator cur = new_constants_.begin()
|
|
|
|
|
; cur != new_constants_.end() ; ++cur) {
|
2011-04-18 02:19:09 +02:00
|
|
|
|
Use separate containers for current and previous scopes
This patch introduces in ScopeBase separate containers
for declarations coming from the current scope and from
the previous scopes.
Until now, in one scope, all objects were kept in an stl map.
When a scope was created inside other scopes, a shallow
copy of the map was made. This solution was nice for
name shadowing (in new scopes, when a name was
encountered, the old objects were overridden by a new
one), but didn't allow for distinguishing where the objects
were allocated. As a result, it is impossible to know who
the owner is and who should delete them.
In this commit ScopeBase gets two containers: for old
and new objects. If a ScopeBase is made from another
ScopeBase object, all objects from the copied object
go to an old_XXX container, where XXX depends on the
type of the copied objects. When a ScopeBase object
is deleted, the objects from new_XXX are deleted and
the ones from old_XXX are not touched.
This patch adds some complexity to the internals
of ScopeBase, but leaves its interface unchanged.
2011-07-20 16:34:36 +02:00
|
|
|
out << "localparam " << cur->first << " = ";
|
|
|
|
|
errors += cur->second->val->emit(out, entity, this);
|
|
|
|
|
out << ";" << endl;
|
2011-03-27 21:01:58 +02:00
|
|
|
}
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
errors += emit_signals(out, entity, this);
|
2011-08-18 05:19:15 +02:00
|
|
|
errors += emit_variables(out, entity, this);
|
2011-04-18 02:19:09 +02:00
|
|
|
|
2011-01-31 20:16:14 +01:00
|
|
|
for (list<Architecture::Statement*>::iterator cur = statements_.begin()
|
|
|
|
|
; cur != statements_.end() ; ++cur) {
|
|
|
|
|
|
|
|
|
|
errors += (*cur)->emit(out, entity, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return errors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Architecture::Statement::emit(ostream&out, Entity*, Architecture*)
|
|
|
|
|
{
|
|
|
|
|
out << " // " << get_fileline() << ": internal error: "
|
|
|
|
|
<< "I don't know how to emit this statement! "
|
|
|
|
|
<< "type=" << typeid(*this).name() << endl;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
|
|
|
|
|
{
|
|
|
|
|
int errors = 0;
|
|
|
|
|
|
|
|
|
|
assert(rval_.size() == 1);
|
|
|
|
|
Expression*rval = rval_.front();
|
|
|
|
|
|
|
|
|
|
out << "// " << get_fileline() << endl;
|
2011-03-27 21:01:58 +02:00
|
|
|
out << "assign ";
|
|
|
|
|
errors += lval_->emit(out, ent, arc);
|
|
|
|
|
out << " = ";
|
2011-01-31 20:16:14 +01:00
|
|
|
|
|
|
|
|
errors += rval->emit(out, ent, arc);
|
|
|
|
|
|
|
|
|
|
out << ";" << endl;
|
|
|
|
|
return errors;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-01 03:50:48 +02:00
|
|
|
int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
|
|
|
|
|
{
|
|
|
|
|
int errors = 0;
|
|
|
|
|
|
|
|
|
|
out << cname_ << " " << iname_ << "(";
|
|
|
|
|
const char*comma = "";
|
2011-07-12 17:51:25 +02:00
|
|
|
for (multimap<perm_string,Expression*>::iterator cur = port_map_.begin()
|
2011-04-01 03:50:48 +02:00
|
|
|
; cur != port_map_.end() ; ++cur) {
|
2011-06-13 01:59:07 +02:00
|
|
|
// Skip unconnected ports
|
|
|
|
|
if (cur->second == 0)
|
|
|
|
|
continue;
|
2011-04-01 03:50:48 +02:00
|
|
|
out << comma << "." << cur->first << "(";
|
|
|
|
|
errors += cur->second->emit(out, ent, arc);
|
|
|
|
|
out << ")";
|
|
|
|
|
comma = ", ";
|
|
|
|
|
}
|
|
|
|
|
out << ");" << endl;
|
|
|
|
|
|
|
|
|
|
return errors;
|
|
|
|
|
}
|
2011-05-15 20:07:42 +02:00
|
|
|
|
|
|
|
|
int ProcessStatement::emit(ostream&out, Entity*ent, Architecture*arc)
|
|
|
|
|
{
|
|
|
|
|
int errors = 0;
|
|
|
|
|
|
|
|
|
|
out << "always";
|
|
|
|
|
|
2011-07-29 02:07:49 +02:00
|
|
|
if (! sensitivity_list_.empty()) {
|
2011-05-15 20:07:42 +02:00
|
|
|
out << " @(";
|
|
|
|
|
const char*comma = 0;
|
|
|
|
|
for (list<Expression*>::iterator cur = sensitivity_list_.begin()
|
|
|
|
|
; cur != sensitivity_list_.end() ; ++cur) {
|
|
|
|
|
|
|
|
|
|
if (comma) out << comma;
|
|
|
|
|
errors += (*cur)->emit(out, ent, arc);
|
|
|
|
|
comma = ", ";
|
|
|
|
|
}
|
|
|
|
|
out << ")";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out << " begin" << endl;
|
|
|
|
|
|
|
|
|
|
for (list<SequentialStmt*>::iterator cur = statements_list_.begin()
|
|
|
|
|
; cur != statements_list_.end() ; ++cur) {
|
2011-08-22 01:40:06 +02:00
|
|
|
errors += (*cur)->emit(out, ent, arc);
|
2011-05-15 20:07:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out << "end" << endl;
|
|
|
|
|
return errors;
|
|
|
|
|
|
|
|
|
|
}
|