Add VHDL if statement to AST types

This commit is contained in:
Nick Gasson 2008-06-11 14:11:37 +01:00
parent b010b8e3ca
commit a7cfdc3a87
5 changed files with 116 additions and 41 deletions

View File

@ -39,7 +39,7 @@ static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc)
ent->get_arch()->add_stmt(vhdl_proc);
ivl_statement_t stmt = ivl_process_stmt(proc);
int rc = draw_stmt(vhdl_proc, stmt);
int rc = draw_stmt(vhdl_proc, vhdl_proc->get_container(), stmt);
if (rc != 0)
return rc;
@ -48,7 +48,7 @@ static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc)
// the end
if (ivl_process_type(proc) == IVL_PR_INITIAL) {
vhdl_wait_stmt *wait = new vhdl_wait_stmt();
vhdl_proc->add_stmt(wait);
vhdl_proc->get_container()->add_stmt(wait);
}
// Add a comment indicating where it came from

View File

@ -37,7 +37,8 @@
* name collision with an existing variable called
* `Verilog_Display_Line' -- do something about this?
*/
static int draw_stask_display(vhdl_process *proc, ivl_statement_t stmt)
static int draw_stask_display(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
// Add the package requirement to the containing entity
proc->get_parent()->get_parent()->requires_package("std.textio");
@ -87,7 +88,7 @@ static int draw_stask_display(vhdl_process *proc, ivl_statement_t stmt)
write->add_expr(ref);
write->add_expr(e);
proc->add_stmt(write);
container->add_stmt(write);
}
// WriteLine(Output, Verilog_Display_Line)
@ -98,7 +99,7 @@ static int draw_stask_display(vhdl_process *proc, ivl_statement_t stmt)
vhdl_var_ref *ref =
new vhdl_var_ref(display_line, vhdl_type::line());
write_line->add_expr(ref);
proc->add_stmt(write_line);
container->add_stmt(write_line);
return 0;
}
@ -110,9 +111,10 @@ static int draw_stask_display(vhdl_process *proc, ivl_statement_t stmt)
* return a failure exit code when in fact it completed
* successfully.
*/
static int draw_stask_finish(vhdl_process *proc, ivl_statement_t stmt)
static int draw_stask_finish(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
proc->add_stmt(new vhdl_assert_stmt("SIMULATION FINISHED"));
container->add_stmt(new vhdl_assert_stmt("SIMULATION FINISHED"));
return 0;
}
@ -120,14 +122,15 @@ static int draw_stask_finish(vhdl_process *proc, ivl_statement_t stmt)
* Generate VHDL for system tasks (like $display). Not all of
* these are supported.
*/
static int draw_stask(vhdl_process *proc, ivl_statement_t stmt)
static int draw_stask(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
const char *name = ivl_stmt_name(stmt);
if (strcmp(name, "$display") == 0)
return draw_stask_display(proc, stmt);
return draw_stask_display(proc, container, stmt);
else if (strcmp(name, "$finish") == 0)
return draw_stask_finish(proc, stmt);
return draw_stask_finish(proc, container, stmt);
else {
error("No VHDL translation for system task %s", name);
return 0;
@ -138,13 +141,14 @@ static int draw_stask(vhdl_process *proc, ivl_statement_t stmt)
* Generate VHDL for a block of Verilog statements. This doesn't
* actually do anything, other than recursively translate the
* block's statements and add them to the process. This is OK as
* `begin' and `end process' function like a Verilog block.
* the stmt_container class behaves like a Verilog block.
*/
static int draw_block(vhdl_process *proc, ivl_statement_t stmt)
static int draw_block(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
int count = ivl_stmt_block_count(stmt);
for (int i = 0; i < count; i++) {
if (draw_stmt(proc, ivl_stmt_block_stmt(stmt, i)) != 0)
if (draw_stmt(proc, container, ivl_stmt_block_stmt(stmt, i)) != 0)
return 1;
}
return 0;
@ -154,9 +158,10 @@ static int draw_block(vhdl_process *proc, ivl_statement_t stmt)
* A no-op statement. This corresponds to a `null' statement in
* VHDL.
*/
static int draw_noop(vhdl_process *proc, ivl_statement_t stmt)
static int draw_noop(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
proc->add_stmt(new vhdl_null_stmt());
container->add_stmt(new vhdl_null_stmt());
return 0;
}
@ -165,7 +170,8 @@ static int draw_noop(vhdl_process *proc, ivl_statement_t stmt)
* this are essentially the same as VHDL's non-blocking signal
* assignment.
*/
static int draw_nbassign(vhdl_process *proc, ivl_statement_t stmt)
static int draw_nbassign(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
int nlvals = ivl_stmt_lvals(stmt);
if (nlvals != 1) {
@ -189,7 +195,7 @@ static int draw_nbassign(vhdl_process *proc, ivl_statement_t stmt)
// The type here can be null as it is never actually needed
vhdl_var_ref *lval_ref = new vhdl_var_ref(signame, NULL);
proc->add_stmt(new vhdl_nbassign_stmt(lval_ref, rhs));
container->add_stmt(new vhdl_nbassign_stmt(lval_ref, rhs));
}
else {
error("Only signals as lvals supported at the moment");
@ -203,7 +209,8 @@ static int draw_nbassign(vhdl_process *proc, ivl_statement_t stmt)
* Delay statements are equivalent to the `wait for' form of the
* VHDL wait statement.
*/
static int draw_delay(vhdl_process *proc, ivl_statement_t stmt)
static int draw_delay(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
uint64_t value = ivl_stmt_delay_val(stmt);
@ -216,14 +223,14 @@ static int draw_delay(vhdl_process *proc, ivl_statement_t stmt)
// the vhdl_process class
vhdl_wait_stmt *wait =
new vhdl_wait_stmt(VHDL_WAIT_FOR_NS, new vhdl_const_int(value));
proc->add_stmt(wait);
container->add_stmt(wait);
// Expand the sub-statement as well
// Often this would result in a useless `null' statement which
// is caught here instead
ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
if (ivl_statement_type(sub_stmt) != IVL_ST_NOOP)
draw_stmt(proc, sub_stmt);
draw_stmt(proc, container, sub_stmt);
return 0;
}
@ -234,7 +241,8 @@ static int draw_delay(vhdl_process *proc, ivl_statement_t stmt)
* TODO: This won't yet handle the posedge to rising_edge, etc.
* mapping.
*/
static int draw_wait(vhdl_process *proc, ivl_statement_t stmt)
static int draw_wait(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
int nevents = ivl_stmt_nevent(stmt);
for (int i = 0; i < nevents; i++) {
@ -271,30 +279,41 @@ static int draw_wait(vhdl_process *proc, ivl_statement_t stmt)
}
ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
draw_stmt(proc, sub_stmt);
draw_stmt(proc, container, sub_stmt);
return 0;
}
static int draw_if(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
return 0;
}
/*
* Generate VHDL statements for the given Verilog statement and
* add them to the given VHDL process.
* add them to the given VHDL process. The container is the
* location to add statements: e.g. the process body, a branch
* of an if statement, etc.
*/
int draw_stmt(vhdl_process *proc, ivl_statement_t stmt)
int draw_stmt(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt)
{
switch (ivl_statement_type(stmt)) {
case IVL_ST_STASK:
return draw_stask(proc, stmt);
return draw_stask(proc, container, stmt);
case IVL_ST_BLOCK:
return draw_block(proc, stmt);
return draw_block(proc, container, stmt);
case IVL_ST_NOOP:
return draw_noop(proc, stmt);
return draw_noop(proc, container, stmt);
case IVL_ST_ASSIGN_NB:
return draw_nbassign(proc, stmt);
return draw_nbassign(proc, container, stmt);
case IVL_ST_DELAY:
return draw_delay(proc, stmt);
return draw_delay(proc, container, stmt);
case IVL_ST_WAIT:
return draw_wait(proc, stmt);
return draw_wait(proc, container, stmt);
case IVL_ST_CONDIT:
return draw_if(proc, container, stmt);
default:
error("No VHDL translation for statement at %s:%d (type = %d)",
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),

View File

@ -193,15 +193,9 @@ vhdl_process::vhdl_process(const char *name)
vhdl_process::~vhdl_process()
{
delete_children<vhdl_seq_stmt>(stmts_);
delete_children<vhdl_decl>(decls_);
}
void vhdl_process::add_stmt(vhdl_seq_stmt* stmt)
{
stmts_.push_back(stmt);
}
void vhdl_process::add_decl(vhdl_decl* decl)
{
decls_.push_back(decl);
@ -244,11 +238,26 @@ void vhdl_process::emit(std::ofstream &of, int level) const
of << "is";
emit_children<vhdl_decl>(of, decls_, level);
of << "begin";
emit_children<vhdl_seq_stmt>(of, stmts_, level);
stmts_.emit(of, level);
of << "end process;";
newline(of, level);
}
stmt_container::~stmt_container()
{
delete_children<vhdl_seq_stmt>(stmts_);
}
void stmt_container::add_stmt(vhdl_seq_stmt *stmt)
{
stmts_.push_back(stmt);
}
void stmt_container::emit(std::ofstream &of, int level) const
{
emit_children<vhdl_seq_stmt>(of, stmts_, level);
}
vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name)
: comp_name_(comp_name), inst_name_(inst_name)
{
@ -548,6 +557,24 @@ void vhdl_assert_stmt::emit(std::ofstream &of, int level) const
of << " report \"" << reason_ << "\" severity failure;";
}
vhdl_if_stmt::~vhdl_if_stmt()
{
delete test_;
}
void vhdl_if_stmt::emit(std::ofstream &of, int level) const
{
of << "if ";
test_->emit(of, level);
of << " then";
newline(of, level);
then_part_.emit(of, level);
of << "else";
newline(of, level);
else_part_.emit(of, level);
of << "end if;";
}
vhdl_unaryop_expr::~vhdl_unaryop_expr()
{
delete operand_;

View File

@ -204,7 +204,20 @@ public:
virtual ~vhdl_seq_stmt() {}
};
typedef std::list<vhdl_seq_stmt*> seq_stmt_list_t;
/*
* A list of sequential statements. For example inside a
* process, loop, or if statement.
*/
class stmt_container {
public:
~stmt_container();
void add_stmt(vhdl_seq_stmt *stmt);
void emit(std::ofstream &of, int level) const;
private:
std::list<vhdl_seq_stmt*> stmts_;
};
/*
@ -262,6 +275,21 @@ private:
};
class vhdl_if_stmt : public vhdl_seq_stmt {
public:
vhdl_if_stmt(vhdl_expr *test)
: test_(test) {}
~vhdl_if_stmt();
stmt_container *get_then_container() { return &then_part_; }
stmt_container *get_else_container() { return &else_part_; }
void emit(std::ofstream &of, int level) const;
private:
vhdl_expr *test_;
stmt_container then_part_, else_part_;
};
/*
* A procedure call. Which is a statement, unlike a function
* call which is an expression.
@ -398,12 +426,12 @@ public:
virtual ~vhdl_process();
void emit(std::ofstream &of, int level) const;
void add_stmt(vhdl_seq_stmt *stmt);
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;
private:
seq_stmt_list_t stmts_;
stmt_container stmts_;
decl_list_t decls_;
std::string name_;
string_list_t sens_;

View File

@ -13,7 +13,8 @@ void error(const char *fmt, ...);
int draw_scope(ivl_scope_t scope, void *_parent);
int draw_process(ivl_process_t net, void *cd);
int draw_stmt(vhdl_process *proc, ivl_statement_t stmt);
int draw_stmt(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt);
vhdl_expr *translate_expr(ivl_expr_t e);