Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1212 lines (990 sloc) 26.361 kb
/*
* VHDL abstract syntax elements.
*
* Copyright (C) 2008-2010 Nick Gasson (nick@nickg.me.uk)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "vhdl_syntax.hh"
#include "vhdl_helper.hh"
#include <cassert>
#include <cstring>
#include <iostream>
#include <typeinfo>
#include <algorithm>
#include <iomanip>
using namespace std;
vhdl_scope::vhdl_scope()
: parent_(NULL), init_(false), sig_assign_(true),
hoisted_init_(false)
{
}
vhdl_scope::~vhdl_scope()
{
}
void vhdl_scope::set_initializing(bool i)
{
init_ = i;
if (parent_)
parent_->set_initializing(i);
}
void vhdl_scope::add_decl(vhdl_decl *decl)
{
decls_.push_back(decl);
}
void vhdl_scope::add_forward_decl(vhdl_decl *decl)
{
decls_.push_front(decl);
}
vhdl_decl *vhdl_scope::get_decl(const std::string &name) const
{
decl_list_t::const_iterator it;
for (it = decls_.begin(); it != decls_.end(); ++it) {
if (strcasecmp((*it)->get_name().c_str(), name.c_str()) == 0)
return *it;
}
return parent_ ? parent_->get_decl(name) : NULL;
}
bool vhdl_scope::have_declared(const std::string &name) const
{
return get_decl(name) != NULL;
}
// True if `name' differs in all but case from another declaration
bool vhdl_scope::name_collides(const string& name) const
{
const vhdl_decl* decl = get_decl(name);
if (decl)
return strcasecmp(decl->get_name().c_str(), name.c_str()) == 0;
else
return false;
}
bool vhdl_scope::contained_within(const vhdl_scope *other) const
{
if (this == other)
return true;
else if (NULL == parent_)
return false;
else
return parent_->contained_within(other);
}
vhdl_scope *vhdl_scope::get_parent() const
{
assert(parent_);
return parent_;
}
bool vhdl_scope::hoisted_initialiser() const
{
return hoisted_init_;
}
void vhdl_scope::hoisted_initialiser(bool h)
{
hoisted_init_ = h;
}
vhdl_entity::vhdl_entity(const string& name, vhdl_arch *arch, int depth__)
: depth(depth__), name_(name), arch_(arch),
time_unit_(TIME_UNIT_NS)
{
arch->get_scope()->set_parent(&ports_);
}
vhdl_entity::~vhdl_entity()
{
}
void vhdl_entity::add_port(vhdl_port_decl *decl)
{
ports_.add_decl(decl);
}
void vhdl_entity::emit(std::ostream &of, int level) const
{
// Pretty much every design will use std_logic so we
// might as well include it by default
of << "library ieee;" << std::endl;
of << "use ieee.std_logic_1164.all;" << std::endl;
of << "use ieee.numeric_std.all;" << std::endl;
of << std::endl;
emit_comment(of, level);
of << "entity " << name_ << " is";
if (!ports_.empty()) {
newline(of, indent(level));
of << "port (";
emit_children<vhdl_decl>(of, ports_.get_decls(), indent(level), ";");
of << ");";
}
newline(of, level);
of << "end entity; ";
blank_line(of, level); // Extra blank line after entities
arch_->emit(of, level);
}
// Return a VHDL time constant scaled to the correct time scale
// for this entity
vhdl_const_time* scale_time(const vhdl_entity* ent, uint64_t t)
{
return new vhdl_const_time(t, ent->time_unit_);
}
// Work out the best VHDL units to use given the Verilog timescale
void vhdl_entity::set_time_units(int units, int precision)
{
int vhdl_units = std::min(units, precision);
if (vhdl_units >= -3)
time_unit_ = TIME_UNIT_MS;
else if (vhdl_units >= -6)
time_unit_ = TIME_UNIT_US;
else if (vhdl_units >= -9)
time_unit_ = TIME_UNIT_NS;
else
time_unit_ = TIME_UNIT_PS;
}
vhdl_arch::~vhdl_arch()
{
}
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)
{
stmts_.push_back(stmt);
}
void vhdl_arch::emit(std::ostream &of, int level) const
{
emit_comment(of, level);
of << "architecture " << name_ << " of " << entity_;
of << " is";
emit_children<vhdl_decl>(of, scope_.get_decls(), level);
of << "begin";
emit_children<vhdl_conc_stmt>(of, stmts_, level);
of << "end architecture;";
blank_line(of, level); // Extra blank line after architectures;
}
void vhdl_procedural::add_blocking_target(vhdl_var_ref* ref)
{
blocking_targets_.insert(ref->get_name());
}
bool vhdl_procedural::is_blocking_target(vhdl_var_ref* ref) const
{
return blocking_targets_.find(ref->get_name()) != blocking_targets_.end();
}
void vhdl_process::add_sensitivity(const std::string &name)
{
sens_.push_back(name);
}
void vhdl_process::emit(std::ostream &of, int level) const
{
// If there are no statements in the body, this process
// can't possibly do anything, so don't bother to emit it
if (stmts_.empty()) {
of << "-- Removed one empty process";
newline(of, level);
return;
}
newline(of, level);
emit_comment(of, level);
if (name_.size() > 0)
of << name_ << ": ";
of << "process ";
int num_sens = sens_.size();
if (num_sens > 0) {
of << "(";
string_list_t::const_iterator it;
for (it = sens_.begin(); it != sens_.end(); ++it) {
of << *it;
if (--num_sens > 0)
of << ", ";
}
of << ") ";
}
of << "is";
emit_children<vhdl_decl>(of, scope_.get_decls(), level);
of << "begin";
stmts_.emit(of, level);
of << "end process;";
}
stmt_container::~stmt_container()
{
}
void stmt_container::add_stmt(vhdl_seq_stmt *stmt)
{
// Add a statement at the end of the block
stmts_.push_back(stmt);
}
/*
* Move all the statements from one container into another.
* This is useful, for example, if we want to wrap a container
* in an `if' statement.
*/
void stmt_container::move_stmts_from(stmt_container *other)
{
copy(other->stmts_.begin(), other->stmts_.end(), back_inserter(stmts_));
other->stmts_.clear();
}
void stmt_container::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
// Iterate over each sub-statement and find all its
// read/written variables
for (stmt_list_t::const_iterator it = stmts_.begin();
it != stmts_.end(); ++it)
(*it)->find_vars(read, write);
}
void stmt_container::emit(std::ostream &of, int level, bool newline) const
{
emit_children<vhdl_seq_stmt>(of, stmts_, level, "", newline);
}
vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name)
: comp_name_(comp_name), inst_name_(inst_name)
{
}
vhdl_comp_inst::~vhdl_comp_inst()
{
}
void vhdl_comp_inst::map_port(const string& name, vhdl_expr *expr)
{
port_map_t pmap = { name, expr };
mapping_.push_back(pmap);
}
void vhdl_comp_inst::emit(std::ostream &of, int level) const
{
newline(of, level);
emit_comment(of, level);
of << inst_name_ << ": " << comp_name_;
// If there are no ports or generics we don't need to mention them...
if (mapping_.size() > 0) {
newline(of, indent(level));
of << "port map (";
int sz = mapping_.size();
port_map_list_t::const_iterator it;
for (it = mapping_.begin(); it != mapping_.end(); ++it) {
newline(of, indent(indent(level)));
of << (*it).name << " => ";
(*it).expr->emit(of, level);
if (--sz > 0)
of << ",";
}
newline(of, indent(level));
of << ")";
}
of << ";";
}
vhdl_component_decl::vhdl_component_decl(const char *name)
: vhdl_decl(name)
{
}
/*
* Create a component declaration for the given entity.
*/
vhdl_component_decl *vhdl_component_decl::component_decl_for(vhdl_entity *ent)
{
assert(ent != NULL);
vhdl_component_decl *decl = new vhdl_component_decl
(ent->get_name().c_str());
decl->ports_ = ent->get_scope()->get_decls();
return decl;
}
void vhdl_component_decl::emit(std::ostream &of, int level) const
{
newline(of, level);
emit_comment(of, level);
of << "component " << name_ << " is";
if (ports_.size() > 0) {
newline(of, indent(level));
of << "port (";
emit_children<vhdl_decl>(of, ports_, indent(level), ";");
of << ");";
}
newline(of, level);
of << "end component;";
}
vhdl_wait_stmt::~vhdl_wait_stmt()
{
}
void vhdl_wait_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
if (expr_)
expr_->find_vars(read);
}
void vhdl_wait_stmt::emit(std::ostream &of, int level) const
{
of << "wait";
switch (type_) {
case VHDL_WAIT_INDEF:
break;
case VHDL_WAIT_FOR:
assert(expr_);
of << " for ";
expr_->emit(of, level);
break;
case VHDL_WAIT_FOR0:
of << " for 0 ns";
break;
case VHDL_WAIT_UNTIL:
assert(expr_);
of << " until ";
expr_->emit(of, level);
break;
case VHDL_WAIT_ON:
{
of << " on ";
string_list_t::const_iterator it = sensitivity_.begin();
while (it != sensitivity_.end()) {
of << *it;
if (++it != sensitivity_.end())
of << ", ";
}
}
break;
}
of << ";";
emit_comment(of, level, true);
}
vhdl_decl::~vhdl_decl()
{
}
// Make a reference object to this declaration
vhdl_var_ref* vhdl_decl::make_ref() const
{
return new vhdl_var_ref(name_, type_);
}
const vhdl_type *vhdl_decl::get_type() const
{
assert(type_);
return type_;
}
void vhdl_decl::set_initial(vhdl_expr *initial)
{
if (!has_initial_) {
assert(initial_ == NULL);
initial_ = initial;
has_initial_ = true;
}
}
void vhdl_port_decl::emit(std::ostream &of, int level) const
{
of << name_ << " : ";
switch (mode_) {
case VHDL_PORT_IN:
of << "in ";
break;
case VHDL_PORT_OUT:
of << "out ";
break;
case VHDL_PORT_INOUT:
of << "inout ";
break;
case VHDL_PORT_BUFFER:
of << "buffer ";
break;
}
type_->emit(of, level);
}
// If this is an `out' port make it a `buffer' so we can read from it
void vhdl_port_decl::ensure_readable()
{
if (mode_ == VHDL_PORT_OUT)
mode_ = VHDL_PORT_BUFFER;
}
// A port is readable if it is not `out'.
// We also make `buffer' ports not readable for these purposes since
// buffers cannot be directly mapped to outputs without an intermediate
// signal.
bool vhdl_port_decl::is_readable() const
{
return mode_ != VHDL_PORT_OUT && mode_ != VHDL_PORT_BUFFER;
}
void vhdl_var_decl::emit(std::ostream &of, int level) const
{
of << "variable " << name_ << " : ";
type_->emit(of, level);
if (initial_) {
of << " := ";
initial_->emit(of, level);
}
of << ";";
emit_comment(of, level, true);
}
void vhdl_signal_decl::emit(std::ostream &of, int level) const
{
of << "signal " << name_ << " : ";
type_->emit(of, level);
if (initial_) {
of << " := ";
initial_->emit(of, level);
}
of << ";";
emit_comment(of, level, true);
}
void vhdl_type_decl::emit(std::ostream &of, int level) const
{
of << "type " << name_ << " is ";
of << type_->get_type_decl_string() << ";";
emit_comment(of, level, true);
}
vhdl_expr::~vhdl_expr()
{
}
void vhdl_expr_list::add_expr(vhdl_expr *e)
{
exprs_.push_back(e);
}
vhdl_expr_list::~vhdl_expr_list()
{
}
void vhdl_expr_list::find_vars(vhdl_var_set_t& read)
{
for (list<vhdl_expr*>::const_iterator it = exprs_.begin();
it != exprs_.end(); ++it)
(*it)->find_vars(read);
}
void vhdl_expr_list::emit(std::ostream &of, int level) const
{
of << "(";
int size = exprs_.size();
std::list<vhdl_expr*>::const_iterator it;
for (it = exprs_.begin(); it != exprs_.end(); ++it) {
(*it)->emit(of, level);
if (--size > 0)
of << ", ";
}
of << ")";
}
void vhdl_pcall_stmt::emit(std::ostream &of, int level) const
{
of << name_;
if (!exprs_.empty())
exprs_.emit(of, level);
of << ";";
}
void vhdl_pcall_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
exprs_.find_vars(read);
}
vhdl_var_ref::~vhdl_var_ref()
{
}
void vhdl_var_ref::set_slice(vhdl_expr *s, int w)
{
assert(type_);
slice_ = s;
slice_width_ = w;
vhdl_type_name_t tname = type_->get_name();
if (tname == VHDL_TYPE_ARRAY) {
type_ = type_->get_base();
}
else {
assert(tname == VHDL_TYPE_UNSIGNED || tname == VHDL_TYPE_SIGNED);
if (w > 0)
type_ = new vhdl_type(tname, w);
else
type_ = vhdl_type::std_logic();
}
}
void vhdl_var_ref::find_vars(vhdl_var_set_t& read)
{
read.insert(this);
}
void vhdl_var_ref::emit(std::ostream &of, int level) const
{
of << name_;
if (slice_) {
of << "(";
if (slice_width_ > 0) {
slice_->emit(of, level);
of << " + " << slice_width_ << " downto ";
}
slice_->emit(of, level);
of << ")";
}
}
void vhdl_const_string::emit(std::ostream &of, int level) const
{
of << "\"" << value_ << "\"";
}
void vhdl_null_stmt::emit(std::ostream &of, int level) const
{
of << "null;";
emit_comment(of, level, true);
}
void vhdl_fcall::find_vars(vhdl_var_set_t& read)
{
exprs_.find_vars(read);
}
void vhdl_fcall::emit(std::ostream &of, int level) const
{
of << name_;
exprs_.emit(of, level);
}
vhdl_abstract_assign_stmt::~vhdl_abstract_assign_stmt()
{
}
void vhdl_abstract_assign_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
lhs_->find_vars(write);
rhs_->find_vars(read);
}
void vhdl_nbassign_stmt::emit(std::ostream &of, int level) const
{
lhs_->emit(of, level);
of << " <= ";
rhs_->emit(of, level);
if (after_) {
of << " after ";
after_->emit(of, level);
}
of << ";";
}
void vhdl_assign_stmt::emit(std::ostream &of, int level) const
{
lhs_->emit(of, level);
of << " := ";
rhs_->emit(of, level);
of << ";";
}
vhdl_const_bits::vhdl_const_bits(const char *value, int width, bool issigned,
bool qualify)
: vhdl_expr(issigned ? vhdl_type::nsigned(width)
: vhdl_type::nunsigned(width), true),
qualified_(qualify),
signed_(issigned)
{
// Can't rely on value being NULL-terminated
while (width--)
value_.push_back(*value++);
}
// True if char is not '1' or '0'
static bool is_meta_bit(char c)
{
return c != '1' && c != '0';
}
// True if the bit strings contains characters other than '1' and '0'
bool vhdl_const_bits::has_meta_bits() const
{
return find_if(value_.begin(), value_.end(), is_meta_bit) != value_.end();
}
void vhdl_const_bits::emit(std::ostream &of, int level) const
{
if (qualified_)
of << (signed_ ? "signed" : "unsigned") << "'(";
// If it's a width we can write in hex, prefer that over binary
size_t bits = value_.size();
int64_t ival = bits_to_int();
if ((!signed_ || ival >= 0)
&& !has_meta_bits() && bits <= 64 && bits % 4 == 0) {
of << "X\"" << hex << setfill('0') << setw(bits / 4) << ival;
}
else {
of << "\"";
std::string::const_reverse_iterator it;
for (it = value_.rbegin(); it != value_.rend(); ++it)
of << vl_to_vhdl_bit(*it);
}
of << (qualified_ ? "\")" : "\"");
}
void vhdl_const_bit::emit(std::ostream &of, int level) const
{
of << "'" << vl_to_vhdl_bit(bit_) << "'";
}
void vhdl_const_int::emit(std::ostream &of, int level) const
{
of << dec << value_;
// We need to find a way to display a comment, since $time, etc. add one.
}
void vhdl_const_bool::emit(std::ostream &of, int level) const
{
of << (value_ ? "True" : "False");
}
void vhdl_const_time::emit(std::ostream &of, int level) const
{
of << dec << value_;
switch (units_) {
case TIME_UNIT_PS: of << " ps"; break;
case TIME_UNIT_NS: of << " ns"; break;
case TIME_UNIT_US: of << " us"; break;
case TIME_UNIT_MS: of << " ms"; break;
}
}
vhdl_cassign_stmt::~vhdl_cassign_stmt()
{
}
void vhdl_cassign_stmt::add_condition(vhdl_expr *value, vhdl_expr *cond)
{
when_part_t when = { value, cond, NULL };
whens_.push_back(when);
}
void vhdl_cassign_stmt::emit(std::ostream &of, int level) const
{
lhs_->emit(of, level);
of << " <= ";
if (!whens_.empty()) {
for (std::list<when_part_t>::const_iterator it = whens_.begin();
it != whens_.end();
++it) {
(*it).value->emit(of, level);
of << " when ";
(*it).cond->emit(of, level);
of << " ";
}
of << "else ";
}
rhs_->emit(of, level);
if (after_) {
of << " after ";
after_->emit(of, level);
}
of << ";";
}
vhdl_report_stmt::vhdl_report_stmt(vhdl_expr *text,
vhdl_severity_t severity)
: severity_(severity),
text_(text)
{
}
void vhdl_report_stmt::emit(ostream& of, int level) const
{
of << "report ";
text_->emit(of, level);
if (severity_ != SEVERITY_NOTE) {
const char *levels[] = { "note", "warning", "error", "failure" };
of << " severity " << levels[severity_];
}
of << ";";
}
void vhdl_report_stmt::find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write)
{
text_->find_vars(read);
}
vhdl_assert_stmt::vhdl_assert_stmt(const char *reason)
: vhdl_report_stmt(new vhdl_const_string(reason), SEVERITY_FAILURE)
{
}
void vhdl_assert_stmt::emit(std::ostream &of, int level) const
{
of << "assert false "; // TODO: Allow arbitrary expression
vhdl_report_stmt::emit(of, level);
}
vhdl_if_stmt::vhdl_if_stmt(vhdl_expr *test)
{
// Need to ensure that the expression is Boolean
vhdl_type boolean(VHDL_TYPE_BOOLEAN);
test_ = test->cast(&boolean);
}
vhdl_if_stmt::~vhdl_if_stmt()
{
}
stmt_container *vhdl_if_stmt::add_elsif(vhdl_expr *test)
{
elsif ef = { test, new stmt_container };
elsif_parts_.push_back(ef);
return ef.container;
}
void vhdl_if_stmt::emit(std::ostream &of, int level) const
{
emit_comment(of, level);
of << "if ";
test_->emit(of, level);
of << " then";
then_part_.emit(of, level);
std::list<elsif>::const_iterator it;
for (it = elsif_parts_.begin(); it != elsif_parts_.end(); ++it) {
of << "elsif ";
(*it).test->emit(of, level);
of << " then";
(*it).container->emit(of, level);
}
if (!else_part_.empty()) {
of << "else";
else_part_.emit(of, level);
}
of << "end if;";
}
void vhdl_if_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
test_->find_vars(read);
then_part_.find_vars(read, write);
else_part_.find_vars(read, write);
for (list<elsif>::const_iterator it = elsif_parts_.begin();
it != elsif_parts_.end(); ++it) {
(*it).test->find_vars(read);
(*it).container->find_vars(read, write);
}
}
int vhdl_expr::paren_levels(0);
void vhdl_expr::open_parens(std::ostream& of)
{
if (paren_levels++ > 0)
of << "(";
}
void vhdl_expr::close_parens(std::ostream& of)
{
assert(paren_levels > 0);
if (--paren_levels > 0)
of << ")";
}
vhdl_unaryop_expr::~vhdl_unaryop_expr()
{
}
void vhdl_unaryop_expr::find_vars(vhdl_var_set_t& read)
{
operand_->find_vars(read);
}
void vhdl_unaryop_expr::emit(std::ostream &of, int level) const
{
open_parens(of);
switch (op_) {
case VHDL_UNARYOP_NOT:
of << "not ";
break;
case VHDL_UNARYOP_NEG:
of << "-";
break;
}
operand_->emit(of, level);
close_parens(of);
}
vhdl_binop_expr::vhdl_binop_expr(vhdl_expr *left, vhdl_binop_t op,
vhdl_expr *right, const vhdl_type *type)
: vhdl_expr(type), op_(op)
{
add_expr(left);
add_expr(right);
}
vhdl_binop_expr::~vhdl_binop_expr()
{
}
void vhdl_binop_expr::add_expr(vhdl_expr *e)
{
operands_.push_back(e);
}
void vhdl_binop_expr::add_expr_front(vhdl_expr *e)
{
operands_.push_front(e);
}
void vhdl_binop_expr::find_vars(vhdl_var_set_t& read)
{
for (list<vhdl_expr*>::const_iterator it = operands_.begin();
it != operands_.end(); ++it)
(*it)->find_vars(read);
}
void vhdl_binop_expr::emit(std::ostream &of, int level) const
{
open_parens(of);
assert(operands_.size() > 0);
std::list<vhdl_expr*>::const_iterator it = operands_.begin();
(*it)->emit(of, level);
while (++it != operands_.end()) {
const char* ops[] = {
"and", "or", "=", "/=", "+", "-", "*", "<",
">", "<=", ">=", "sll", "srl", "xor", "&",
"nand", "nor", "xnor", "/", "mod", "**", "sra", NULL
};
of << " " << ops[op_] << " ";
(*it)->emit(of, level);
}
close_parens(of);
}
vhdl_bit_spec_expr::~vhdl_bit_spec_expr()
{
}
void vhdl_bit_spec_expr::add_bit(int bit, vhdl_expr *e)
{
bit_map bm = { bit, e };
bits_.push_back(bm);
}
void vhdl_bit_spec_expr::emit(std::ostream &of, int level) const
{
of << "(";
std::list<bit_map>::const_iterator it;
it = bits_.begin();
while (it != bits_.end()) {
of << (*it).bit << " => ";
(*it).e->emit(of, level);
if (++it != bits_.end())
of << ", ";
}
if (others_) {
of << (bits_.empty() ? "" : ", ") << "others => ";
others_->emit(of, level);
}
of << ")";
}
vhdl_case_branch::~vhdl_case_branch()
{
}
void vhdl_case_branch::emit(std::ostream &of, int level) const
{
of << "when ";
when_->emit(of, level);
of << " =>";
stmts_.emit(of, indent(level), false);
}
vhdl_case_stmt::~vhdl_case_stmt()
{
}
void vhdl_case_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
test_->find_vars(read);
for (case_branch_list_t::const_iterator it = branches_.begin();
it != branches_.end(); ++it) {
(*it)->when_->find_vars(read);
(*it)->stmts_.find_vars(read, write);
}
}
void vhdl_case_stmt::emit(std::ostream &of, int level) const
{
of << "case ";
test_->emit(of, level);
of << " is";
newline(of, indent(level));
case_branch_list_t::const_iterator it;
int n = branches_.size();
for (it = branches_.begin(); it != branches_.end(); ++it) {
(*it)->emit(of, level);
if (--n > 0)
newline(of, indent(level));
else
newline(of, level);
}
of << "end case;";
}
vhdl_while_stmt::~vhdl_while_stmt()
{
}
void vhdl_while_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
test_->find_vars(read);
vhdl_loop_stmt::find_vars(read, write);
}
void vhdl_while_stmt::emit(std::ostream &of, int level) const
{
of << "while ";
test_->emit(of, level);
of << " ";
vhdl_loop_stmt::emit(of, level);
}
void vhdl_loop_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
stmts_.find_vars(read, write);
}
void vhdl_loop_stmt::emit(std::ostream &of, int level) const
{
of << "loop";
stmts_.emit(of, level);
of << "end loop;";
}
vhdl_for_stmt::~vhdl_for_stmt()
{
}
void vhdl_for_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
from_->find_vars(read);
to_->find_vars(write);
vhdl_loop_stmt::find_vars(read, write);
}
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_decl(name, ret_type)
{
// A function contains two scopes:
// scope_ = The parameters
// variables_ = Local variables
// A call to get_scope returns variables_ whose parent is scope_
variables_.set_parent(&scope_);
}
void vhdl_function::emit(std::ostream &of, int level) const
{
newline(of, level);
emit_comment(of, level);
of << "function " << name_ << " (";
emit_children<vhdl_decl>(of, scope_.get_decls(), level, ";");
of << ") ";
newline(of, level);
of << "return " << type_->get_string() << " is";
emit_children<vhdl_decl>(of, variables_.get_decls(), level);
of << "begin";
stmts_.emit(of, level);
of << " return " << name_ << "_Result;";
newline(of, level);
of << "end function;";
}
void vhdl_forward_fdecl::emit(std::ostream &of, int level) const
{
of << "function " << f_->get_name() << " (";
emit_children<vhdl_decl>(of, f_->scope_.get_decls(), level, ";");
of << ") ";
newline(of, level);
of << "return " << f_->type_->get_string() << ";";
newline(of, level);
}
void vhdl_param_decl::emit(std::ostream &of, int level) const
{
of << name_ << " : ";
type_->emit(of, level);
}
vhdl_with_select_stmt::~vhdl_with_select_stmt()
{
}
void vhdl_with_select_stmt::emit(std::ostream &of, int level) const
{
of << "with ";
test_->emit(of, level);
of << " select";
emit_comment(of, level, true);
newline(of, indent(level));
out_->emit(of, level);
of << " <= ";
when_list_t::const_iterator it = whens_.begin();
while (it != whens_.end()) {
(*it).value->emit(of, level);
if ((*it).delay) {
of << " after ";
(*it).delay->emit(of, level);
}
of << " when ";
(*it).cond->emit(of, level);
if (++it != whens_.end() || others_ != NULL) {
of << ",";
newline(of, indent(level));
}
else
of << ";";
}
if (others_) {
others_->emit(of, level);
of << " when others;";
}
}
void vhdl_with_select_stmt::add_condition(vhdl_expr *value, vhdl_expr *cond, vhdl_expr *delay)
{
when_part_t when = { value, cond, delay };
whens_.push_back(when);
}
void vhdl_with_select_stmt::add_default(vhdl_expr* value)
{
others_ = value;
}
Jump to Line
Something went wrong with that request. Please try again.