Add VHDL if statement to AST types
This commit is contained in:
parent
b010b8e3ca
commit
a7cfdc3a87
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue