Generate VHDL processes from Verilog processes

This commit is contained in:
Nick Gasson 2008-06-02 16:17:01 +01:00
parent fef0fd82ff
commit 9292a087e8
6 changed files with 76 additions and 21 deletions

View File

@ -22,13 +22,57 @@
#include "vhdl_element.hh"
#include <iostream>
#include <cassert>
#include <sstream>
/*
* Convert a Verilog process to VHDL and add it to the architecture
* of the given entity.
*/
static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc)
{
vhdl_process *vhdl_proc = new vhdl_process();
// TODO: Add statements
// Add a comment indicating where it came from
ivl_scope_t scope = ivl_process_scope(proc);
const char *type = ivl_process_type(proc) == IVL_PR_INITIAL
? "initial" : "always";
std::ostringstream ss;
ss << "Generated from " << type << " process in scope ";
ss << ivl_scope_name(scope);
vhdl_proc->set_comment(ss.str());
// Store it in the entity's architecture
ent->get_arch()->add_stmt(vhdl_proc);
return 0;
}
int draw_process(ivl_process_t proc, void *cd)
{
ivl_scope_t scope = ivl_process_scope(proc);
const char *scope_name = ivl_scope_name(scope);
std::cout << "process: scope " << scope_name << std::endl;
return 0;
// A process should occur in a module scope, therefore it
// should have already been assigned a VHDL entity
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
vhdl_entity *ent = find_entity(ivl_scope_tname(scope));
assert(ent != NULL);
// If the scope this process belongs to is the same as the
// VHDL entity was generated from, then create a VHDL process
// from this Verilog process. This ensures that each process
// is translated at most once, no matter how many times it
// appears in the hierarchy.
if (ent->get_derived_from() == scope_name) {
std::cout << "New process encountered in " << scope_name << std::endl;
return generate_vhdl_process(ent, proc);
}
else {
std::cout << "Ignoring already seen process in ";
std::cout << scope_name << std::endl;
return 0;
}
}

View File

@ -35,12 +35,16 @@ static vhdl_entity *create_entity_for(ivl_scope_t scope)
// The type name will become the entity name
const char *tname = ivl_scope_tname(scope);
// Remember the scope name this entity was derived from so
// the correct processes can be added later
const char *derived_from = ivl_scope_name(scope);
// Verilog does not have the entity/architecture distinction
// so we always create a pair and associate the architecture
// with the entity for convenience (this also means that we
// retain a 1-to-1 mapping of scope to VHDL element)
vhdl_arch *arch = new vhdl_arch(tname);
vhdl_entity *ent = new vhdl_entity(tname, arch);
vhdl_entity *ent = new vhdl_entity(tname, derived_from, arch);
// Build a comment to add to the entity/architecture
std::ostringstream ss;
@ -51,6 +55,9 @@ static vhdl_entity *create_entity_for(ivl_scope_t scope)
arch->set_comment(ss.str());
ent->set_comment(ss.str());
std::cout << "Generated entity " << tname;
std::cout << " from " << ivl_scope_name(scope) << std::endl;
remember_entity(ent);
return ent;
}
@ -67,10 +74,6 @@ static int draw_module(ivl_scope_t scope, ivl_scope_t parent)
if (NULL == ent)
ent = create_entity_for(scope);
assert(ent);
if (parent != NULL) {
std::cout << "parent " << ivl_scope_name(parent) << std::endl;
}
return 0;
}

View File

@ -51,11 +51,11 @@ void error(const char *fmt, ...)
/*
* Find an entity given a type name.
*/
vhdl_entity *find_entity(const char *tname)
vhdl_entity *find_entity(const std::string &tname)
{
entity_list_t::const_iterator it;
for (it = g_entities.begin(); it != g_entities.end(); ++it) {
if (strcmp((*it)->get_name(), tname) == 0)
if ((*it)->get_name() == tname)
return *it;
}
return NULL;

View File

@ -85,8 +85,9 @@ void vhdl_element::emit_comment(std::ofstream &of, int level) const
//////// ENTITY ////////
vhdl_entity::vhdl_entity(const char *name, vhdl_arch *arch)
: name_(name), arch_(arch)
vhdl_entity::vhdl_entity(const char *name, const char *derived_from,
vhdl_arch *arch)
: name_(name), arch_(arch), derived_from_(derived_from)
{
}
@ -169,7 +170,7 @@ void vhdl_process::add_stmt(vhdl_seq_stmt* stmt)
void vhdl_process::emit(std::ofstream &of, int level) const
{
emit_comment(of, level);
if (name_)
if (name_.size() > 0)
of << name_ << ": ";
of << "process is"; // TODO: sensitivity
newline(of, level);

View File

@ -72,19 +72,20 @@ typedef std::list<vhdl_seq_stmt*> seq_stmt_list_t;
*/
class vhdl_process : public vhdl_conc_stmt {
public:
vhdl_process(const char *name = NULL);
vhdl_process(const char *name = "");
virtual ~vhdl_process();
void emit(std::ofstream &of, int level) const;
void add_stmt(vhdl_seq_stmt* stmt);
private:
seq_stmt_list_t stmts_;
const char *name_;
std::string name_;
};
/*
* An architecture which implements an entity.
* An architecture which implements an entity. Entities are `derived'
* from instantiations of Verilog module scopes in the hierarchy.
*/
class vhdl_arch : public vhdl_element {
public:
@ -95,7 +96,7 @@ public:
void add_stmt(vhdl_conc_stmt* stmt);
private:
conc_stmt_list_t stmts_;
const char *name_, *entity_;
std::string name_, entity_;
};
/*
@ -105,15 +106,19 @@ private:
*/
class vhdl_entity : public vhdl_element {
public:
vhdl_entity(const char *name, vhdl_arch *arch);
vhdl_entity(const char *name, const char *derived_from,
vhdl_arch *arch);
virtual ~vhdl_entity();
void emit(std::ofstream &of, int level=0) const;
vhdl_arch *get_arch() const { return arch_; }
const char *get_name() const { return name_; }
const std::string &get_name() const { return name_; }
const std::string &get_derived_from() const { return derived_from_; }
private:
const char *name_;
std::string name_;
vhdl_arch *arch_; // Entity may only have a single architecture
std::string derived_from_;
};
typedef std::list<vhdl_entity*> entity_list_t;

View File

@ -6,13 +6,15 @@
#include "vhdl_element.hh"
#include <string>
void error(const char *fmt, ...);
int draw_scope(ivl_scope_t scope, void *_parent);
int draw_process(ivl_process_t net, void *cd);
void remember_entity(vhdl_entity *ent);
vhdl_entity *find_entity(const char *tname);
vhdl_entity *find_entity(const std::string &tname);
#endif /* #ifndef INC_VHDL_TARGET_H */