Merge branch 'vhdl' of git@github.com:nickg/iverilog into vhdl
This commit is contained in:
commit
ba462eb8b7
|
|
@ -149,6 +149,9 @@ static vhdl_expr *translate_unary(ivl_expr_t e)
|
||||||
case '~':
|
case '~':
|
||||||
return new vhdl_unaryop_expr
|
return new vhdl_unaryop_expr
|
||||||
(VHDL_UNARYOP_NOT, operand, new vhdl_type(*operand->get_type()));
|
(VHDL_UNARYOP_NOT, operand, new vhdl_type(*operand->get_type()));
|
||||||
|
case '-':
|
||||||
|
return new vhdl_unaryop_expr
|
||||||
|
(VHDL_UNARYOP_NEG, operand, new vhdl_type(*operand->get_type()));
|
||||||
case 'N': // NOR
|
case 'N': // NOR
|
||||||
return translate_reduction(SF_REDUCE_OR, true, operand);
|
return translate_reduction(SF_REDUCE_OR, true, operand);
|
||||||
case '|':
|
case '|':
|
||||||
|
|
@ -352,8 +355,10 @@ static vhdl_expr *translate_select(ivl_expr_t e)
|
||||||
{
|
{
|
||||||
vhdl_var_ref *from =
|
vhdl_var_ref *from =
|
||||||
dynamic_cast<vhdl_var_ref*>(translate_expr(ivl_expr_oper1(e)));
|
dynamic_cast<vhdl_var_ref*>(translate_expr(ivl_expr_oper1(e)));
|
||||||
if (NULL == from)
|
if (NULL == from) {
|
||||||
|
error("Can only select from variable reference");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ivl_expr_t o2 = ivl_expr_oper2(e);
|
ivl_expr_t o2 = ivl_expr_oper2(e);
|
||||||
if (o2) {
|
if (o2) {
|
||||||
|
|
@ -481,3 +486,21 @@ vhdl_expr *translate_expr(ivl_expr_t e)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Translate an expression into a time. This is achieved simply
|
||||||
|
* by multiplying the expression by 1ns.
|
||||||
|
*/
|
||||||
|
vhdl_expr *translate_time_expr(ivl_expr_t e)
|
||||||
|
{
|
||||||
|
vhdl_expr *time = translate_expr(e);
|
||||||
|
if (NULL == time)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||||
|
time = time->cast(&integer);
|
||||||
|
|
||||||
|
vhdl_expr *ns1 = new vhdl_const_time(1, TIME_UNIT_NS);
|
||||||
|
return new vhdl_binop_expr(time, VHDL_BINOP_MULT, ns1,
|
||||||
|
vhdl_type::time());
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,13 @@ static void declare_logic(vhdl_arch *arch, ivl_scope_t scope)
|
||||||
continue; // Not suitable for continuous assignment
|
continue; // Not suitable for continuous assignment
|
||||||
|
|
||||||
vhdl_expr *rhs = translate_logic(arch->get_scope(), log);
|
vhdl_expr *rhs = translate_logic(arch->get_scope(), log);
|
||||||
arch->add_stmt(new vhdl_cassign_stmt(lhs, rhs));
|
vhdl_cassign_stmt *ass = new vhdl_cassign_stmt(lhs, rhs);
|
||||||
|
|
||||||
|
ivl_expr_t delay = ivl_logic_delay(log, 1);
|
||||||
|
if (delay)
|
||||||
|
ass->set_after(translate_time_expr(delay));
|
||||||
|
|
||||||
|
arch->add_stmt(ass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -269,19 +269,8 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
container->add_stmt(a);
|
container->add_stmt(a);
|
||||||
|
|
||||||
ivl_expr_t i_delay;
|
ivl_expr_t i_delay;
|
||||||
if (NULL == after && (i_delay = ivl_stmt_delay_expr(stmt))) {
|
if (NULL == after && (i_delay = ivl_stmt_delay_expr(stmt)))
|
||||||
if ((after = translate_expr(i_delay)) == NULL)
|
after = translate_time_expr(i_delay);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// Need to make 'after' a time value
|
|
||||||
// we can do this by multiplying by 1ns
|
|
||||||
vhdl_type integer(VHDL_TYPE_INTEGER);
|
|
||||||
after = after->cast(&integer);
|
|
||||||
|
|
||||||
vhdl_expr *ns1 = new vhdl_const_time(1, TIME_UNIT_NS);
|
|
||||||
after = new vhdl_binop_expr(after, VHDL_BINOP_MULT, ns1,
|
|
||||||
vhdl_type::time());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (after != NULL)
|
if (after != NULL)
|
||||||
a->set_after(after);
|
a->set_after(after);
|
||||||
|
|
@ -349,16 +338,9 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
|
||||||
time = new vhdl_const_time(value, TIME_UNIT_NS);
|
time = new vhdl_const_time(value, TIME_UNIT_NS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
time = translate_expr(ivl_stmt_delay_expr(stmt));
|
time = translate_time_expr(ivl_stmt_delay_expr(stmt));
|
||||||
if (NULL == time)
|
if (NULL == time)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
vhdl_type integer(VHDL_TYPE_INTEGER);
|
|
||||||
time = time->cast(&integer);
|
|
||||||
|
|
||||||
vhdl_expr *ns1 = new vhdl_const_time(1, TIME_UNIT_NS);
|
|
||||||
time = new vhdl_binop_expr(time, VHDL_BINOP_MULT, ns1,
|
|
||||||
vhdl_type::time());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the sub-statement is an assignment then VHDL lets
|
// If the sub-statement is an assignment then VHDL lets
|
||||||
|
|
@ -577,6 +559,37 @@ int draw_while(vhdl_procedural *proc, stmt_container *container,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int draw_forever(vhdl_procedural *proc, stmt_container *container,
|
||||||
|
ivl_statement_t stmt)
|
||||||
|
{
|
||||||
|
vhdl_loop_stmt *loop = new vhdl_loop_stmt;
|
||||||
|
container->add_stmt(loop);
|
||||||
|
|
||||||
|
draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int draw_repeat(vhdl_procedural *proc, stmt_container *container,
|
||||||
|
ivl_statement_t stmt)
|
||||||
|
{
|
||||||
|
vhdl_expr *times = translate_expr(ivl_stmt_cond_expr(stmt));
|
||||||
|
if (NULL == times)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||||
|
times = times->cast(&integer);
|
||||||
|
|
||||||
|
const char *it_name = "Verilog_Repeat";
|
||||||
|
vhdl_for_stmt *loop =
|
||||||
|
new vhdl_for_stmt(it_name, new vhdl_const_int(1), times);
|
||||||
|
container->add_stmt(loop);
|
||||||
|
|
||||||
|
draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate VHDL statements for the given Verilog statement and
|
* Generate VHDL statements for the given Verilog statement and
|
||||||
* add them to the given VHDL process. The container is the
|
* add them to the given VHDL process. The container is the
|
||||||
|
|
@ -611,6 +624,10 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container,
|
||||||
return draw_case(proc, container, stmt);
|
return draw_case(proc, container, stmt);
|
||||||
case IVL_ST_WHILE:
|
case IVL_ST_WHILE:
|
||||||
return draw_while(proc, container, stmt);
|
return draw_while(proc, container, stmt);
|
||||||
|
case IVL_ST_FOREVER:
|
||||||
|
return draw_forever(proc, container, stmt);
|
||||||
|
case IVL_ST_REPEAT:
|
||||||
|
return draw_repeat(proc, container, stmt);
|
||||||
default:
|
default:
|
||||||
error("No VHDL translation for statement at %s:%d (type = %d)",
|
error("No VHDL translation for statement at %s:%d (type = %d)",
|
||||||
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
|
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,9 @@ void support_function::emit(std::ostream &of, int level) const
|
||||||
of << "(B : Boolean) return std_logic is" << nl_string(level)
|
of << "(B : Boolean) return std_logic is" << nl_string(level)
|
||||||
<< "begin" << nl_string(indent(level))
|
<< "begin" << nl_string(indent(level))
|
||||||
<< "if B then" << nl_string(indent(indent(level)))
|
<< "if B then" << nl_string(indent(indent(level)))
|
||||||
<< "return '1'" << nl_string(indent(level))
|
<< "return '1';" << nl_string(indent(level))
|
||||||
<< "else" << nl_string(indent(indent(level)))
|
<< "else" << nl_string(indent(indent(level)))
|
||||||
<< "return '0'" << nl_string(indent(level))
|
<< "return '0';" << nl_string(indent(level))
|
||||||
<< "end if;" << nl_string(level);
|
<< "end if;" << nl_string(level);
|
||||||
break;
|
break;
|
||||||
case SF_REDUCE_OR:
|
case SF_REDUCE_OR:
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@
|
||||||
template <class T>
|
template <class T>
|
||||||
void emit_children(std::ostream &of,
|
void emit_children(std::ostream &of,
|
||||||
const std::list<T*> &children,
|
const std::list<T*> &children,
|
||||||
int level, const char *delim="")
|
int level, const char *delim = "",
|
||||||
|
bool trailing_newline = true)
|
||||||
{
|
{
|
||||||
// Don't indent if there are no children
|
// Don't indent if there are no children
|
||||||
if (children.size() == 0)
|
if (children.size() == 0)
|
||||||
|
|
@ -42,7 +43,8 @@ void emit_children(std::ostream &of,
|
||||||
if (--sz > 0)
|
if (--sz > 0)
|
||||||
of << delim;
|
of << delim;
|
||||||
}
|
}
|
||||||
newline(of, level);
|
if (trailing_newline)
|
||||||
|
newline(of, level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,9 +192,9 @@ void stmt_container::add_stmt(vhdl_seq_stmt *stmt)
|
||||||
stmts_.push_back(stmt);
|
stmts_.push_back(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stmt_container::emit(std::ostream &of, int level) const
|
void stmt_container::emit(std::ostream &of, int level, bool newline) const
|
||||||
{
|
{
|
||||||
emit_children<vhdl_seq_stmt>(of, stmts_, level);
|
emit_children<vhdl_seq_stmt>(of, stmts_, level, "", newline);
|
||||||
}
|
}
|
||||||
|
|
||||||
vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name)
|
vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name)
|
||||||
|
|
@ -611,6 +611,12 @@ void vhdl_cassign_stmt::emit(std::ostream &of, int level) const
|
||||||
of << "else ";
|
of << "else ";
|
||||||
}
|
}
|
||||||
rhs_->emit(of, level);
|
rhs_->emit(of, level);
|
||||||
|
|
||||||
|
if (after_) {
|
||||||
|
of << " after ";
|
||||||
|
after_->emit(of, level);
|
||||||
|
}
|
||||||
|
|
||||||
of << ";";
|
of << ";";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -657,6 +663,9 @@ void vhdl_unaryop_expr::emit(std::ostream &of, int level) const
|
||||||
case VHDL_UNARYOP_NOT:
|
case VHDL_UNARYOP_NOT:
|
||||||
of << "not ";
|
of << "not ";
|
||||||
break;
|
break;
|
||||||
|
case VHDL_UNARYOP_NEG:
|
||||||
|
of << "-";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
operand_->emit(of, level);
|
operand_->emit(of, level);
|
||||||
of << ")";
|
of << ")";
|
||||||
|
|
@ -715,7 +724,7 @@ void vhdl_case_branch::emit(std::ostream &of, int level) const
|
||||||
of << "when ";
|
of << "when ";
|
||||||
when_->emit(of, level);
|
when_->emit(of, level);
|
||||||
of << " =>";
|
of << " =>";
|
||||||
stmts_.emit(of, indent(level));
|
stmts_.emit(of, indent(level), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
vhdl_case_stmt::~vhdl_case_stmt()
|
vhdl_case_stmt::~vhdl_case_stmt()
|
||||||
|
|
@ -731,8 +740,14 @@ void vhdl_case_stmt::emit(std::ostream &of, int level) const
|
||||||
newline(of, indent(level));
|
newline(of, indent(level));
|
||||||
|
|
||||||
case_branch_list_t::const_iterator it;
|
case_branch_list_t::const_iterator it;
|
||||||
for (it = branches_.begin(); it != branches_.end(); ++it)
|
int n = branches_.size();
|
||||||
|
for (it = branches_.begin(); it != branches_.end(); ++it) {
|
||||||
(*it)->emit(of, level);
|
(*it)->emit(of, level);
|
||||||
|
if (--n > 0)
|
||||||
|
newline(of, indent(level));
|
||||||
|
else
|
||||||
|
newline(of, level);
|
||||||
|
}
|
||||||
|
|
||||||
of << "end case;";
|
of << "end case;";
|
||||||
}
|
}
|
||||||
|
|
@ -746,11 +761,33 @@ void vhdl_while_stmt::emit(std::ostream &of, int level) const
|
||||||
{
|
{
|
||||||
of << "while ";
|
of << "while ";
|
||||||
test_->emit(of, level);
|
test_->emit(of, level);
|
||||||
of << " loop";
|
of << " ";
|
||||||
|
vhdl_loop_stmt::emit(of, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vhdl_loop_stmt::emit(std::ostream &of, int level) const
|
||||||
|
{
|
||||||
|
of << "loop";
|
||||||
stmts_.emit(of, level);
|
stmts_.emit(of, level);
|
||||||
of << "end loop;";
|
of << "end loop;";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vhdl_for_stmt::~vhdl_for_stmt()
|
||||||
|
{
|
||||||
|
delete from_;
|
||||||
|
delete to_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vhdl_for_stmt::emit(std::ostream &of, int level) const
|
||||||
|
{
|
||||||
|
of << "for " << lname_ << " in ";
|
||||||
|
from_->emit(of, level);
|
||||||
|
of << " to ";
|
||||||
|
to_->emit(of, level);
|
||||||
|
of << " ";
|
||||||
|
vhdl_loop_stmt::emit(of, level);
|
||||||
|
}
|
||||||
|
|
||||||
vhdl_function::vhdl_function(const char *name, vhdl_type *ret_type)
|
vhdl_function::vhdl_function(const char *name, vhdl_type *ret_type)
|
||||||
: vhdl_decl(name, ret_type)
|
: vhdl_decl(name, ret_type)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ private:
|
||||||
|
|
||||||
enum vhdl_unaryop_t {
|
enum vhdl_unaryop_t {
|
||||||
VHDL_UNARYOP_NOT,
|
VHDL_UNARYOP_NOT,
|
||||||
|
VHDL_UNARYOP_NEG,
|
||||||
};
|
};
|
||||||
|
|
||||||
class vhdl_unaryop_expr : public vhdl_expr {
|
class vhdl_unaryop_expr : public vhdl_expr {
|
||||||
|
|
@ -226,14 +227,15 @@ typedef std::list<vhdl_conc_stmt*> conc_stmt_list_t;
|
||||||
class vhdl_cassign_stmt : public vhdl_conc_stmt {
|
class vhdl_cassign_stmt : public vhdl_conc_stmt {
|
||||||
public:
|
public:
|
||||||
vhdl_cassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs)
|
vhdl_cassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs)
|
||||||
: lhs_(lhs), rhs_(rhs) {}
|
: lhs_(lhs), rhs_(rhs), after_(NULL) {}
|
||||||
~vhdl_cassign_stmt();
|
~vhdl_cassign_stmt();
|
||||||
|
|
||||||
void emit(std::ostream &of, int level) const;
|
void emit(std::ostream &of, int level) const;
|
||||||
void add_condition(vhdl_expr *value, vhdl_expr *cond);
|
void add_condition(vhdl_expr *value, vhdl_expr *cond);
|
||||||
|
void set_after(vhdl_expr *a) { after_ = a; }
|
||||||
private:
|
private:
|
||||||
vhdl_var_ref *lhs_;
|
vhdl_var_ref *lhs_;
|
||||||
vhdl_expr *rhs_;
|
vhdl_expr *rhs_, *after_;
|
||||||
|
|
||||||
struct when_part_t {
|
struct when_part_t {
|
||||||
vhdl_expr *value, *cond;
|
vhdl_expr *value, *cond;
|
||||||
|
|
@ -259,7 +261,7 @@ public:
|
||||||
~stmt_container();
|
~stmt_container();
|
||||||
|
|
||||||
void add_stmt(vhdl_seq_stmt *stmt);
|
void add_stmt(vhdl_seq_stmt *stmt);
|
||||||
void emit(std::ostream &of, int level) const;
|
void emit(std::ostream &of, int level, bool newline=true) const;
|
||||||
bool empty() const { return stmts_.empty(); }
|
bool empty() const { return stmts_.empty(); }
|
||||||
private:
|
private:
|
||||||
std::list<vhdl_seq_stmt*> stmts_;
|
std::list<vhdl_seq_stmt*> stmts_;
|
||||||
|
|
@ -393,19 +395,41 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class vhdl_while_stmt : public vhdl_seq_stmt {
|
class vhdl_loop_stmt : public vhdl_seq_stmt {
|
||||||
public:
|
public:
|
||||||
vhdl_while_stmt(vhdl_expr *test) : test_(test) {}
|
virtual ~vhdl_loop_stmt() {}
|
||||||
~vhdl_while_stmt();
|
|
||||||
|
|
||||||
stmt_container *get_container() { return &stmts_; }
|
stmt_container *get_container() { return &stmts_; }
|
||||||
void emit(std::ostream &of, int level) const;
|
void emit(std::ostream &of, int level) const;
|
||||||
private:
|
private:
|
||||||
vhdl_expr *test_;
|
|
||||||
stmt_container stmts_;
|
stmt_container stmts_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class vhdl_while_stmt : public vhdl_loop_stmt {
|
||||||
|
public:
|
||||||
|
vhdl_while_stmt(vhdl_expr *test) : test_(test) {}
|
||||||
|
~vhdl_while_stmt();
|
||||||
|
|
||||||
|
void emit(std::ostream &of, int level) const;
|
||||||
|
private:
|
||||||
|
vhdl_expr *test_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class vhdl_for_stmt : public vhdl_loop_stmt {
|
||||||
|
public:
|
||||||
|
vhdl_for_stmt(const char *lname, vhdl_expr *from, vhdl_expr *to)
|
||||||
|
: lname_(lname), from_(from), to_(to) {}
|
||||||
|
~vhdl_for_stmt();
|
||||||
|
|
||||||
|
void emit(std::ostream &of, int level) const;
|
||||||
|
private:
|
||||||
|
const char *lname_;
|
||||||
|
vhdl_expr *from_, *to_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A procedure call. Which is a statement, unlike a function
|
* A procedure call. Which is a statement, unlike a function
|
||||||
* call which is an expression.
|
* call which is an expression.
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container,
|
||||||
int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm);
|
int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm);
|
||||||
|
|
||||||
vhdl_expr *translate_expr(ivl_expr_t e);
|
vhdl_expr *translate_expr(ivl_expr_t e);
|
||||||
|
vhdl_expr *translate_time_expr(ivl_expr_t e);
|
||||||
vhdl_var_ref *lpm_output(vhdl_scope *scope, ivl_lpm_t lpm);
|
vhdl_var_ref *lpm_output(vhdl_scope *scope, ivl_lpm_t lpm);
|
||||||
|
|
||||||
void remember_entity(vhdl_entity *ent);
|
void remember_entity(vhdl_entity *ent);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue