Refactor code to use the new vhdl_scope class

This commit is contained in:
Nick Gasson 2008-06-24 18:52:25 +01:00
parent ba36e47575
commit 63b1887ff2
8 changed files with 64 additions and 163 deletions

View File

@ -115,14 +115,11 @@ static void flush_string(std::ostringstream &ss, stmt_container *container)
int draw_stask_display(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt, bool newline)
{
// Add the package requirement to the containing entity
proc->get_parent()->get_parent()->requires_package("std.textio");
if (!proc->have_declared_var(DISPLAY_LINE)) {
if (!proc->get_scope()->have_declared(DISPLAY_LINE)) {
vhdl_var_decl *line_var =
new vhdl_var_decl(DISPLAY_LINE, vhdl_type::line());
line_var->set_comment("For generating $display output");
proc->add_decl(line_var);
proc->get_scope()->add_decl(line_var);
}
// Write the data into the line

View File

@ -25,15 +25,15 @@
static int draw_binop_lpm(vhdl_arch *arch, ivl_lpm_t lpm, vhdl_binop_t op)
{
vhdl_expr *lhs = nexus_to_var_ref(arch, ivl_lpm_data(lpm, 0));
vhdl_expr *lhs = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, 0));
if (NULL == lhs)
return 1;
vhdl_expr *rhs = nexus_to_var_ref(arch, ivl_lpm_data(lpm, 1));
vhdl_expr *rhs = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, 1));
if (NULL == rhs)
return 1;
vhdl_var_ref *out = nexus_to_var_ref(arch, ivl_lpm_q(lpm, 0));
vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0));
if (NULL == out)
return 1;

View File

@ -86,12 +86,12 @@ void blocking_assign_to(vhdl_process *proc, ivl_signal_t sig)
// This is the first time a non-blocking assignment
// has been made to this signal: create a variable
// to shadow it.
if (!proc->have_declared_var(tmpname)) {
vhdl_decl *decl = proc->get_parent()->get_decl(var);
if (!proc->get_scope()->have_declared(tmpname)) {
vhdl_decl *decl = proc->get_scope()->get_decl(var);
assert(decl);
vhdl_type *type = new vhdl_type(*decl->get_type());
proc->add_decl(new vhdl_var_decl(tmpname.c_str(), type));
proc->get_scope()->add_decl(new vhdl_var_decl(tmpname.c_str(), type));
}
rename_signal(sig, tmpname);
@ -110,7 +110,7 @@ void draw_blocking_assigns(vhdl_process *proc, stmt_container *container)
for (it = g_assign_vars.begin(); it != g_assign_vars.end(); ++it) {
std::string stripped(strip_var((*it).first));
vhdl_decl *decl = proc->get_decl(stripped);
vhdl_decl *decl = proc->get_scope()->get_decl(stripped);
assert(decl);
vhdl_type *type = new vhdl_type(*decl->get_type());

View File

@ -25,11 +25,12 @@
#include <sstream>
#include <cassert>
/*
* Given a nexus and an architecture, find the first signal
* Given a nexus and an architecture scope, find the first signal
* that is connected to the nexus, if there is one.
*/
vhdl_var_ref *nexus_to_var_ref(vhdl_arch *arch, ivl_nexus_t nexus)
vhdl_var_ref *nexus_to_var_ref(vhdl_scope *arch_scope, ivl_nexus_t nexus)
{
int nptrs = ivl_nexus_ptrs(nexus);
for (int i = 0; i < nptrs; i++) {
@ -39,7 +40,7 @@ vhdl_var_ref *nexus_to_var_ref(vhdl_arch *arch, ivl_nexus_t nexus)
if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) {
const char *signame = get_renamed_signal(sig).c_str();
vhdl_decl *decl = arch->get_decl(signame);
vhdl_decl *decl = arch_scope->get_decl(signame);
assert(decl);
vhdl_type *type = new vhdl_type(*(decl->get_type()));
@ -67,7 +68,7 @@ static vhdl_expr *inputs_to_expr(vhdl_arch *arch, vhdl_binop_t op,
int npins = ivl_logic_pins(log);
for (int i = 1; i < npins; i++) {
ivl_nexus_t input = ivl_logic_pin(log, i);
gate->add_expr(nexus_to_var_ref(arch, input));
gate->add_expr(nexus_to_var_ref(arch->get_scope(), input));
}
return gate;
@ -82,7 +83,7 @@ static vhdl_expr *input_to_expr(vhdl_arch *arch, vhdl_unaryop_t op,
ivl_nexus_t input = ivl_logic_pin(log, 1);
assert(input);
vhdl_expr *operand = nexus_to_var_ref(arch, input);
vhdl_expr *operand = nexus_to_var_ref(arch->get_scope(), input);
return new vhdl_unaryop_expr(op, operand, vhdl_type::std_logic());
}
@ -98,7 +99,7 @@ static void declare_logic(vhdl_arch *arch, ivl_scope_t scope)
// The output is always pin zero
ivl_nexus_t output = ivl_logic_pin(log, 0);
vhdl_var_ref *lhs = nexus_to_var_ref(arch, output);
vhdl_var_ref *lhs = nexus_to_var_ref(arch->get_scope(), output);
vhdl_expr *rhs = NULL;
switch (ivl_logic_type(log)) {
@ -123,9 +124,9 @@ static void declare_logic(vhdl_arch *arch, ivl_scope_t scope)
}
/*
* Declare all signals for a scope in an architecture.
* Declare all signals and ports for a scope.
*/
static void declare_signals(vhdl_arch *arch, ivl_scope_t scope)
static void declare_signals(vhdl_entity *ent, ivl_scope_t scope)
{
int nsigs = ivl_scope_sigs(scope);
for (int i = 0; i < nsigs; i++) {
@ -140,7 +141,7 @@ static void declare_signals(vhdl_arch *arch, ivl_scope_t scope)
else
sig_type = vhdl_type::nunsigned(width);
remember_signal(sig, arch->get_parent());
remember_signal(sig, ent);
// Make sure the signal name conforms to VHDL naming rules
std::string name(ivl_signal_basename(sig));
@ -162,14 +163,14 @@ static void declare_signals(vhdl_arch *arch, ivl_scope_t scope)
ivl_signal_port_t mode = ivl_signal_port(sig);
switch (mode) {
case IVL_SIP_NONE:
arch->add_decl(new vhdl_signal_decl(name.c_str(), sig_type));
ent->get_arch()->add_decl(new vhdl_signal_decl(name.c_str(), sig_type));
break;
case IVL_SIP_INPUT:
arch->get_parent()->add_port
ent->get_scope()->add_decl
(new vhdl_port_decl(name.c_str(), sig_type, VHDL_PORT_IN));
break;
case IVL_SIP_OUTPUT:
arch->get_parent()->add_port
ent->get_scope()->add_decl
(new vhdl_port_decl(name.c_str(), sig_type, VHDL_PORT_OUT));
if (ivl_signal_type(sig) == IVL_SIT_REG) {
@ -183,18 +184,18 @@ static void declare_signals(vhdl_arch *arch, ivl_scope_t scope)
rename_signal(sig, newname.c_str());
vhdl_type *reg_type = new vhdl_type(*sig_type);
arch->add_decl(new vhdl_signal_decl(newname.c_str(), reg_type));
ent->get_arch()->add_decl(new vhdl_signal_decl(newname.c_str(), reg_type));
// Create a concurrent assignment statement to
// connect the register to the output
arch->add_stmt
ent->get_arch()->add_stmt
(new vhdl_cassign_stmt
(new vhdl_var_ref(name.c_str(), NULL),
new vhdl_var_ref(newname.c_str(), NULL)));
}
break;
case IVL_SIP_INOUT:
arch->get_parent()->add_port
ent->get_scope()->add_decl
(new vhdl_port_decl(name.c_str(), sig_type, VHDL_PORT_INOUT));
break;
}
@ -231,10 +232,10 @@ static vhdl_entity *create_entity_for(ivl_scope_t scope)
// retain a 1-to-1 mapping of scope to VHDL element)
vhdl_arch *arch = new vhdl_arch(tname, "FromVerilog");
vhdl_entity *ent = new vhdl_entity(tname, derived_from, arch);
// Locate all the signals in this module and add them to
// the architecture
declare_signals(arch, scope);
declare_signals(ent, scope);
// Similarly, add all the primitive logic gates
declare_logic(arch, scope);
@ -344,7 +345,7 @@ static int draw_module(ivl_scope_t scope, ivl_scope_t parent)
assert(parent_arch != NULL);
// Create a forward declaration for it
if (!parent_arch->have_declared_component(ent->get_name())) {
if (!parent_arch->have_declared(ent->get_name())) {
vhdl_decl *comp_decl = vhdl_component_decl::component_decl_for(ent);
parent_arch->add_decl(comp_decl);
}

View File

@ -43,7 +43,7 @@ static int draw_stask_finish(vhdl_process *proc, stmt_container *container,
{
const char *use_vhpi = ivl_design_flag(get_vhdl_design(), "use-vhpi-finish");
if (strcmp(use_vhpi, "1") == 0) {
proc->get_parent()->get_parent()->requires_package("work.Verilog_Support");
//get_active_entity()->requires_package("work.Verilog_Support");
container->add_stmt(new vhdl_pcall_stmt("work.Verilog_Support.Finish"));
}
else {
@ -121,7 +121,7 @@ static int draw_nbassign(vhdl_process *proc, stmt_container *container,
if ((sig = ivl_lval_sig(lval))) {
const char *signame = get_renamed_signal(sig).c_str();
vhdl_decl *decl = proc->get_parent()->get_decl(signame);
vhdl_decl *decl = proc->get_scope()->get_decl(signame);
assert(decl);
vhdl_expr *rhs_raw = translate_expr(ivl_stmt_rval(stmt));
@ -175,7 +175,7 @@ static int draw_assign(vhdl_process *proc, stmt_container *container,
if ((sig = ivl_lval_sig(lval))) {
const std::string signame(get_renamed_signal(sig));
vhdl_decl *decl = proc->get_decl(signame);
vhdl_decl *decl = proc->get_scope()->get_decl(signame);
assert(decl);
vhdl_expr *rhs_raw = translate_expr(ivl_stmt_rval(stmt));
@ -186,7 +186,7 @@ static int draw_assign(vhdl_process *proc, stmt_container *container,
// As with non-blocking assignment, push constant assignments
// into the initialisation if we can
if (proc->is_initial() && ivl_signal_port(sig) == IVL_SIP_NONE
&& rhs->constant() && !proc->have_declared_var(signame)) {
&& rhs->constant() && !proc->get_scope()->have_declared(signame)) {
decl->set_initial(rhs);
// This signal may be used e.g. in a loop test so we need
@ -295,7 +295,7 @@ static int draw_delay(vhdl_process *proc, stmt_container *container,
static void edge_detector(ivl_nexus_t nexus, vhdl_process *proc,
vhdl_binop_expr *test, const char *type)
{
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_parent(), nexus);
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope()->get_parent(), nexus);
vhdl_fcall *detect = new vhdl_fcall(type, vhdl_type::boolean());
detect->add_expr(ref);
test->add_expr(detect);
@ -334,7 +334,7 @@ static int draw_wait(vhdl_process *proc, stmt_container *container,
// Only add this signal to the sensitivity if it's part
// of the containing architecture (i.e. it has already
// been declared)
if (proc->get_parent()->have_declared(signame)) {
if (proc->get_scope()->get_parent()->have_declared(signame)) {
proc->add_sensitivity(signame);
non_edges.push_back(signame);
break;
@ -418,7 +418,7 @@ static int draw_case(vhdl_process *proc, stmt_container *container,
// TODO: Check if this is already declared
const char *tmp_name = "Verilog_Case_Ex";
vhdl_type *test_type = new vhdl_type(*test->get_type());
proc->add_decl(new vhdl_var_decl(tmp_name, test_type));
proc->get_scope()->add_decl(new vhdl_var_decl(tmp_name, test_type));
vhdl_var_ref *tmp_ref = new vhdl_var_ref(tmp_name, NULL);
container->add_stmt(new vhdl_assign_stmt(tmp_ref, test));

View File

@ -57,11 +57,17 @@ bool vhdl_scope::have_declared(const std::string &name) const
return get_decl(name) != NULL;
}
vhdl_scope *vhdl_scope::get_parent()
{
assert(parent_);
return parent_;
}
vhdl_entity::vhdl_entity(const char *name, const char *derived_from,
vhdl_arch *arch)
: name_(name), arch_(arch), derived_from_(derived_from)
{
arch->parent_ = this;
arch->get_scope()->set_parent(&ports_);
}
vhdl_entity::~vhdl_entity()
@ -69,29 +75,6 @@ vhdl_entity::~vhdl_entity()
delete arch_;
}
/*
* Add a package to the list of `use' statements before
* the entity.
*/
void vhdl_entity::requires_package(const char *spec)
{
std::string pname(spec);
std::list<std::string>::iterator it;
for (it = uses_.begin(); it != uses_.end(); ++it) {
if (*it == pname)
return;
}
uses_.push_back(spec);
}
/*
* Find a port declaration by name
*/
vhdl_decl *vhdl_entity::get_decl(const std::string &name) const
{
return ports_.get_decl(name);
}
void vhdl_entity::add_port(vhdl_port_decl *decl)
{
ports_.add_decl(decl);
@ -104,11 +87,7 @@ void vhdl_entity::emit(std::ofstream &of, int level) const
of << "library ieee;" << std::endl;
of << "use ieee.std_logic_1164.all;" << std::endl;
of << "use ieee.numeric_std.all;" << std::endl;
for (std::list<std::string>::const_iterator it = uses_.begin();
it != uses_.end();
++it)
of << "use " << *it << ".all;" << std::endl;
of << "use std.textio.all;" << std::endl;
of << std::endl;
emit_comment(of, level);
@ -128,7 +107,7 @@ void vhdl_entity::emit(std::ofstream &of, int level) const
}
vhdl_arch::vhdl_arch(const char *entity, const char *name)
: parent_(NULL), name_(name), entity_(entity)
: name_(name), entity_(entity)
{
}
@ -136,24 +115,22 @@ vhdl_arch::vhdl_arch(const char *entity, const char *name)
vhdl_arch::~vhdl_arch()
{
delete_children<vhdl_conc_stmt>(stmts_);
delete_children<vhdl_decl>(decls_);
}
void vhdl_arch::add_stmt(vhdl_process *proc)
{
proc->get_scope()->set_parent(&scope_);
stmts_.push_back(proc);
}
void vhdl_arch::add_stmt(vhdl_conc_stmt *stmt)
{
stmt->parent_ = this;
stmts_.push_back(stmt);
}
void vhdl_arch::add_decl(vhdl_decl *decl)
{
decls_.push_back(decl);
}
vhdl_entity *vhdl_arch::get_parent() const
{
assert(parent_);
return parent_;
scope_.add_decl(decl);
}
void vhdl_arch::emit(std::ofstream &of, int level) const
@ -161,7 +138,7 @@ void vhdl_arch::emit(std::ofstream &of, int level) const
emit_comment(of, level);
of << "architecture " << name_ << " of " << entity_;
of << " is";
emit_children<vhdl_decl>(of, decls_, level);
emit_children<vhdl_decl>(of, scope_.get_decls(), level);
of << "begin";
emit_children<vhdl_conc_stmt>(of, stmts_, level);
of << "end architecture;";
@ -170,32 +147,7 @@ void vhdl_arch::emit(std::ofstream &of, int level) const
vhdl_decl *vhdl_arch::get_decl(const std::string &name) const
{
decl_list_t::const_iterator it;
for (it = decls_.begin(); it != decls_.end(); ++it) {
if ((*it)->get_name() == name)
return *it;
}
// Maybe it's a port rather than an internal signal?
assert(parent_);
return parent_->get_decl(name);
}
/*
* True if component `name' has already been declared in this
* architecture. This is a bit of hack, since it uses typeid
* to distinguish between components and other declarations.
*/
bool vhdl_arch::have_declared_component(const std::string &name) const
{
std::string comp_typename(typeid(vhdl_component_decl).name());
decl_list_t::const_iterator it;
for (it = decls_.begin(); it != decls_.end(); ++it) {
if (comp_typename == typeid(**it).name()
&& (*it)->get_name() == name)
return true;
}
return false;
return scope_.get_decl(name);
}
/*
@ -204,14 +156,9 @@ bool vhdl_arch::have_declared_component(const std::string &name) const
*/
bool vhdl_arch::have_declared(const std::string &name) const
{
return get_decl(name) != NULL;
return scope_.have_declared(name);
}
vhdl_arch *vhdl_conc_stmt::get_parent() const
{
assert(parent_);
return parent_;
}
vhdl_process::vhdl_process(const char *name)
: name_(name), initial_(false)
@ -219,44 +166,11 @@ vhdl_process::vhdl_process(const char *name)
}
vhdl_process::~vhdl_process()
{
delete_children<vhdl_decl>(decls_);
}
void vhdl_process::add_decl(vhdl_decl* decl)
{
decls_.push_back(decl);
}
vhdl_decl *vhdl_process::get_decl(const std::string &name) const
{
decl_list_t::const_iterator it;
for (it = decls_.begin(); it != decls_.end(); ++it) {
if ((*it)->get_name() == name)
return *it;
}
// Maybe it's a signal rather than a variable?
assert(get_parent());
return get_parent()->get_decl(name);
}
void vhdl_process::add_sensitivity(const char *name)
{
sens_.push_back(name);
}
bool vhdl_process::have_declared_var(const std::string &name) const
{
decl_list_t::const_iterator it;
for (it = decls_.begin(); it != decls_.end(); ++it) {
if ((*it)->get_name() == name)
return true;
}
return false;
}
void vhdl_process::emit(std::ofstream &of, int level) const
{
// If there are no statements in the body, this process
@ -285,7 +199,7 @@ void vhdl_process::emit(std::ofstream &of, int level) const
}
of << "is";
emit_children<vhdl_decl>(of, decls_, level);
emit_children<vhdl_decl>(of, scope_.get_decls(), level);
of << "begin";
stmts_.emit(of, level);
of << "end process;";

View File

@ -203,14 +203,8 @@ private:
* processes.
*/
class vhdl_conc_stmt : public vhdl_element {
friend class vhdl_arch; // Can set its parent
public:
vhdl_conc_stmt() : parent_(NULL) {}
virtual ~vhdl_conc_stmt() {}
vhdl_arch *get_parent() const;
private:
vhdl_arch *parent_;
};
typedef std::list<vhdl_conc_stmt*> conc_stmt_list_t;
@ -532,9 +526,11 @@ public:
void add_decl(vhdl_decl *decl);
vhdl_decl *get_decl(const std::string &name) const;
bool have_declared(const std::string &name) const;
vhdl_scope *get_parent();
bool empty() const { return decls_.empty(); }
const decl_list_t &get_decls() const { return decls_; }
void set_parent(vhdl_scope *p) { parent_ = p; }
private:
decl_list_t decls_;
vhdl_scope *parent_;
@ -544,19 +540,16 @@ private:
class vhdl_process : public vhdl_conc_stmt {
public:
vhdl_process(const char *name = "");
virtual ~vhdl_process();
void emit(std::ofstream &of, int level) const;
stmt_container *get_container() { return &stmts_; }
void add_decl(vhdl_decl *decl);
void add_sensitivity(const char *name);
bool have_declared_var(const std::string &name) const;
vhdl_decl *get_decl(const std::string &name) const;
vhdl_scope *get_scope() { return &scope_; }
void set_initial(bool i) { initial_ = i; }
bool is_initial() const { return initial_; }
private:
stmt_container stmts_;
decl_list_t decls_;
vhdl_scope scope_;
std::string name_;
string_list_t sens_;
bool initial_;
@ -567,22 +560,20 @@ private:
* An architecture which implements an entity.
*/
class vhdl_arch : public vhdl_element {
friend class vhdl_entity; // Can set its parent
public:
vhdl_arch(const char *entity, const char *name);
virtual ~vhdl_arch();
void emit(std::ofstream &of, int level=0) const;
bool have_declared_component(const std::string &name) const;
bool have_declared(const std::string &name) const;
vhdl_decl *get_decl(const std::string &name) const;
void add_decl(vhdl_decl *decl);
void add_stmt(vhdl_process *proc);
void add_stmt(vhdl_conc_stmt *stmt);
vhdl_entity *get_parent() const;
vhdl_scope *get_scope() { return &scope_; }
private:
vhdl_entity *parent_;
conc_stmt_list_t stmts_;
decl_list_t decls_;
vhdl_scope scope_;
std::string name_, entity_;
};
@ -601,9 +592,7 @@ public:
void emit(std::ofstream &of, int level=0) const;
void add_port(vhdl_port_decl *decl);
vhdl_arch *get_arch() const { return arch_; }
vhdl_decl *get_decl(const std::string &name) const;
const std::string &get_name() const { return name_; }
void requires_package(const char *spec);
const std::string &get_derived_from() const { return derived_from_; }
vhdl_scope *get_scope() { return &ports_; }
@ -611,7 +600,6 @@ private:
std::string name_;
vhdl_arch *arch_; // Entity may only have a single architecture
std::string derived_from_;
string_list_t uses_;
vhdl_scope ports_;
};

View File

@ -23,8 +23,9 @@ void remember_entity(vhdl_entity *ent);
vhdl_entity *find_entity(const std::string &tname);
ivl_design_t get_vhdl_design();
vhdl_entity *get_active_entity();
vhdl_var_ref *nexus_to_var_ref(vhdl_arch *arch, ivl_nexus_t nexus);
vhdl_var_ref *nexus_to_var_ref(vhdl_scope *arch_scope, ivl_nexus_t nexus);
void remember_signal(ivl_signal_t sig, const vhdl_entity *ent);
void rename_signal(ivl_signal_t sig, const std::string &renamed);