2008-06-08 14:27:48 +02:00
|
|
|
/*
|
|
|
|
|
* VHDL abstract syntax elements.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2008 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>
|
2008-06-09 17:27:04 +02:00
|
|
|
#include <iostream>
|
2008-06-24 11:55:45 +02:00
|
|
|
#include <typeinfo>
|
2008-06-08 14:27:48 +02:00
|
|
|
|
2008-06-24 19:12:00 +02:00
|
|
|
vhdl_scope::vhdl_scope()
|
2008-06-25 23:15:57 +02:00
|
|
|
: parent_(NULL), init_(false), sig_assign_(true)
|
2008-06-24 19:12:00 +02:00
|
|
|
{
|
2008-07-16 13:00:11 +02:00
|
|
|
|
2008-06-24 19:12:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vhdl_scope::~vhdl_scope()
|
|
|
|
|
{
|
|
|
|
|
delete_children<vhdl_decl>(decls_);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-16 13:00:11 +02:00
|
|
|
void vhdl_scope::set_initializing(bool i)
|
|
|
|
|
{
|
|
|
|
|
init_ = i;
|
|
|
|
|
if (parent_)
|
|
|
|
|
parent_->set_initializing(i);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-24 19:12:00 +02:00
|
|
|
void vhdl_scope::add_decl(vhdl_decl *decl)
|
|
|
|
|
{
|
|
|
|
|
decls_.push_back(decl);
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-03 11:50:31 +02:00
|
|
|
void vhdl_scope::add_forward_decl(vhdl_decl *decl)
|
|
|
|
|
{
|
|
|
|
|
decls_.push_front(decl);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-24 19:12:00 +02:00
|
|
|
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 ((*it)->get_name() == name)
|
|
|
|
|
return *it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return parent_ ? parent_->get_decl(name) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool vhdl_scope::have_declared(const std::string &name) const
|
|
|
|
|
{
|
|
|
|
|
return get_decl(name) != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-29 13:00:26 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-14 20:13:11 +02:00
|
|
|
vhdl_scope *vhdl_scope::get_parent() const
|
2008-06-24 19:52:25 +02:00
|
|
|
{
|
|
|
|
|
assert(parent_);
|
|
|
|
|
return parent_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
vhdl_entity::vhdl_entity(const char *name, const char *derived_from,
|
|
|
|
|
vhdl_arch *arch)
|
|
|
|
|
: name_(name), arch_(arch), derived_from_(derived_from)
|
|
|
|
|
{
|
2008-06-24 19:52:25 +02:00
|
|
|
arch->get_scope()->set_parent(&ports_);
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vhdl_entity::~vhdl_entity()
|
|
|
|
|
{
|
|
|
|
|
delete arch_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-09 17:27:04 +02:00
|
|
|
void vhdl_entity::add_port(vhdl_port_decl *decl)
|
|
|
|
|
{
|
2008-06-24 19:12:00 +02:00
|
|
|
ports_.add_decl(decl);
|
2008-06-09 17:27:04 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_entity::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
// 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;
|
2008-06-14 19:03:25 +02:00
|
|
|
of << "use ieee.numeric_std.all;" << std::endl;
|
2008-06-24 19:52:25 +02:00
|
|
|
of << "use std.textio.all;" << std::endl;
|
2008-06-08 14:27:48 +02:00
|
|
|
of << std::endl;
|
|
|
|
|
|
|
|
|
|
emit_comment(of, level);
|
|
|
|
|
of << "entity " << name_ << " is";
|
2008-06-09 17:37:05 +02:00
|
|
|
|
2008-06-24 19:12:00 +02:00
|
|
|
if (!ports_.empty()) {
|
2008-06-09 17:37:05 +02:00
|
|
|
newline(of, indent(level));
|
|
|
|
|
of << "port (";
|
2008-06-24 19:12:00 +02:00
|
|
|
emit_children<vhdl_decl>(of, ports_.get_decls(), indent(level), ";");
|
2008-06-09 17:37:05 +02:00
|
|
|
of << ");";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
newline(of, level);
|
|
|
|
|
of << "end entity; ";
|
|
|
|
|
blank_line(of, level); // Extra blank line after entities
|
|
|
|
|
arch_->emit(of, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vhdl_arch::~vhdl_arch()
|
|
|
|
|
{
|
|
|
|
|
delete_children<vhdl_conc_stmt>(stmts_);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-24 19:52:25 +02:00
|
|
|
void vhdl_arch::add_stmt(vhdl_process *proc)
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-24 19:52:25 +02:00
|
|
|
proc->get_scope()->set_parent(&scope_);
|
|
|
|
|
stmts_.push_back(proc);
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-24 19:52:25 +02:00
|
|
|
void vhdl_arch::add_stmt(vhdl_conc_stmt *stmt)
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-24 19:52:25 +02:00
|
|
|
stmts_.push_back(stmt);
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_arch::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
emit_comment(of, level);
|
|
|
|
|
of << "architecture " << name_ << " of " << entity_;
|
|
|
|
|
of << " is";
|
2008-06-24 19:52:25 +02:00
|
|
|
emit_children<vhdl_decl>(of, scope_.get_decls(), level);
|
2008-06-08 14:27:48 +02:00
|
|
|
of << "begin";
|
|
|
|
|
emit_children<vhdl_conc_stmt>(of, stmts_, level);
|
|
|
|
|
of << "end architecture;";
|
|
|
|
|
blank_line(of, level); // Extra blank line after architectures;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vhdl_process::add_sensitivity(const char *name)
|
|
|
|
|
{
|
|
|
|
|
sens_.push_back(name);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_process::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-13 15:17:24 +02:00
|
|
|
// 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;
|
|
|
|
|
}
|
2008-08-02 11:45:38 +02:00
|
|
|
|
|
|
|
|
newline(of, level);
|
2008-06-08 14:27:48 +02:00
|
|
|
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";
|
2008-06-24 19:52:25 +02:00
|
|
|
emit_children<vhdl_decl>(of, scope_.get_decls(), level);
|
2008-06-08 14:27:48 +02:00
|
|
|
of << "begin";
|
2008-06-11 15:11:37 +02:00
|
|
|
stmts_.emit(of, level);
|
2008-06-08 14:27:48 +02:00
|
|
|
of << "end process;";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-11 15:11:37 +02:00
|
|
|
stmt_container::~stmt_container()
|
|
|
|
|
{
|
|
|
|
|
delete_children<vhdl_seq_stmt>(stmts_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stmt_container::add_stmt(vhdl_seq_stmt *stmt)
|
|
|
|
|
{
|
|
|
|
|
stmts_.push_back(stmt);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-23 15:31:41 +02:00
|
|
|
void stmt_container::emit(std::ostream &of, int level, bool newline) const
|
2008-06-11 15:11:37 +02:00
|
|
|
{
|
2008-07-23 15:31:41 +02:00
|
|
|
emit_children<vhdl_seq_stmt>(of, stmts_, level, "", newline);
|
2008-06-11 15:11:37 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name)
|
|
|
|
|
: comp_name_(comp_name), inst_name_(inst_name)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-10 15:00:15 +02:00
|
|
|
vhdl_comp_inst::~vhdl_comp_inst()
|
|
|
|
|
{
|
|
|
|
|
port_map_list_t::iterator it;
|
|
|
|
|
for (it = mapping_.begin(); it != mapping_.end(); ++it) {
|
|
|
|
|
delete (*it).expr;
|
|
|
|
|
}
|
|
|
|
|
mapping_.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-10 14:58:41 +02:00
|
|
|
void vhdl_comp_inst::map_port(const char *name, vhdl_expr *expr)
|
|
|
|
|
{
|
|
|
|
|
port_map_t pmap = { name, expr };
|
|
|
|
|
mapping_.push_back(pmap);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_comp_inst::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-08-03 15:50:13 +02:00
|
|
|
newline(of, level);
|
2008-06-08 14:27:48 +02:00
|
|
|
emit_comment(of, level);
|
2008-06-10 14:58:41 +02:00
|
|
|
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 << ";";
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vhdl_component_decl::vhdl_component_decl(const char *name)
|
|
|
|
|
: vhdl_decl(name)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Create a component declaration for the given entity.
|
|
|
|
|
*/
|
2008-06-24 19:12:00 +02:00
|
|
|
vhdl_component_decl *vhdl_component_decl::component_decl_for(vhdl_entity *ent)
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
assert(ent != NULL);
|
|
|
|
|
|
|
|
|
|
vhdl_component_decl *decl = new vhdl_component_decl
|
|
|
|
|
(ent->get_name().c_str());
|
|
|
|
|
|
2008-06-24 19:12:00 +02:00
|
|
|
decl->ports_ = ent->get_scope()->get_decls();
|
2008-06-10 12:24:16 +02:00
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
return decl;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_component_decl::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-07-31 22:17:49 +02:00
|
|
|
newline(of, level);
|
2008-06-08 14:27:48 +02:00
|
|
|
emit_comment(of, level);
|
|
|
|
|
of << "component " << name_ << " is";
|
2008-06-10 12:24:16 +02:00
|
|
|
|
|
|
|
|
if (ports_.size() > 0) {
|
|
|
|
|
newline(of, indent(level));
|
|
|
|
|
of << "port (";
|
|
|
|
|
emit_children<vhdl_decl>(of, ports_, indent(level), ";");
|
|
|
|
|
of << ");";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
newline(of, level);
|
|
|
|
|
of << "end component;";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-09 13:40:59 +02:00
|
|
|
vhdl_wait_stmt::~vhdl_wait_stmt()
|
|
|
|
|
{
|
|
|
|
|
if (expr_ != NULL)
|
|
|
|
|
delete expr_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_wait_stmt::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-09 13:40:59 +02:00
|
|
|
of << "wait";
|
|
|
|
|
|
|
|
|
|
switch (type_) {
|
|
|
|
|
case VHDL_WAIT_INDEF:
|
|
|
|
|
break;
|
2008-06-19 13:16:19 +02:00
|
|
|
case VHDL_WAIT_FOR:
|
2008-06-09 13:40:59 +02:00
|
|
|
assert(expr_);
|
|
|
|
|
of << " for ";
|
|
|
|
|
expr_->emit(of, level);
|
|
|
|
|
break;
|
2008-07-14 21:29:49 +02:00
|
|
|
case VHDL_WAIT_UNTIL:
|
|
|
|
|
assert(expr_);
|
|
|
|
|
of << " until ";
|
|
|
|
|
expr_->emit(of, level);
|
|
|
|
|
break;
|
2008-07-17 18:23:21 +02:00
|
|
|
case VHDL_WAIT_ON:
|
|
|
|
|
{
|
2008-07-17 18:36:42 +02:00
|
|
|
of << " on ";
|
2008-07-17 18:23:21 +02:00
|
|
|
string_list_t::const_iterator it = sensitivity_.begin();
|
|
|
|
|
while (it != sensitivity_.end()) {
|
|
|
|
|
of << *it;
|
|
|
|
|
if (++it != sensitivity_.end())
|
|
|
|
|
of << ", ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2008-06-09 13:40:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
of << ";";
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-09 17:27:04 +02:00
|
|
|
vhdl_decl::~vhdl_decl()
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-09 17:27:04 +02:00
|
|
|
if (type_ != NULL)
|
|
|
|
|
delete type_;
|
2008-06-13 15:10:28 +02:00
|
|
|
if (initial_ != NULL)
|
|
|
|
|
delete initial_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-25 18:29:09 +02:00
|
|
|
const vhdl_type *vhdl_decl::get_type() const
|
|
|
|
|
{
|
|
|
|
|
assert(type_);
|
|
|
|
|
return type_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-13 15:10:28 +02:00
|
|
|
void vhdl_decl::set_initial(vhdl_expr *initial)
|
2008-07-16 13:00:11 +02:00
|
|
|
{
|
|
|
|
|
if (!has_initial_) {
|
|
|
|
|
assert(initial_ == NULL);
|
|
|
|
|
initial_ = initial;
|
|
|
|
|
has_initial_ = true;
|
|
|
|
|
}
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_port_decl::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-09 17:27:04 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
type_->emit(of, level);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_var_decl::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-09 17:27:04 +02:00
|
|
|
of << "variable " << name_ << " : ";
|
|
|
|
|
type_->emit(of, level);
|
2008-06-13 15:10:28 +02:00
|
|
|
|
|
|
|
|
if (initial_) {
|
|
|
|
|
of << " := ";
|
|
|
|
|
initial_->emit(of, level);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-09 17:27:04 +02:00
|
|
|
of << ";";
|
|
|
|
|
emit_comment(of, level, true);
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_signal_decl::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
of << "signal " << name_ << " : ";
|
|
|
|
|
type_->emit(of, level);
|
2008-06-13 15:10:28 +02:00
|
|
|
|
|
|
|
|
if (initial_) {
|
|
|
|
|
of << " := ";
|
|
|
|
|
initial_->emit(of, level);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
of << ";";
|
|
|
|
|
emit_comment(of, level, true);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-17 14:08:55 +02:00
|
|
|
void vhdl_type_decl::emit(std::ostream &of, int level) const
|
2008-07-17 12:59:02 +02:00
|
|
|
{
|
|
|
|
|
of << "type " << name_ << " is ";
|
2008-07-17 14:08:55 +02:00
|
|
|
of << type_->get_type_decl_string() << ";";
|
2008-07-17 12:59:02 +02:00
|
|
|
emit_comment(of, level, true);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
vhdl_expr::~vhdl_expr()
|
|
|
|
|
{
|
2008-06-09 15:08:27 +02:00
|
|
|
if (type_ != NULL)
|
2008-06-09 13:54:21 +02:00
|
|
|
delete type_;
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vhdl_expr_list::add_expr(vhdl_expr *e)
|
|
|
|
|
{
|
|
|
|
|
exprs_.push_back(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vhdl_expr_list::~vhdl_expr_list()
|
|
|
|
|
{
|
|
|
|
|
delete_children<vhdl_expr>(exprs_);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_expr_list::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
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 << ")";
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_pcall_stmt::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
of << name_;
|
2008-06-17 21:16:16 +02:00
|
|
|
if (!exprs_.empty())
|
|
|
|
|
exprs_.emit(of, level);
|
2008-06-08 14:27:48 +02:00
|
|
|
of << ";";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-21 17:17:44 +02:00
|
|
|
vhdl_var_ref::~vhdl_var_ref()
|
|
|
|
|
{
|
|
|
|
|
if (slice_)
|
|
|
|
|
delete slice_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-07 22:19:59 +02:00
|
|
|
void vhdl_var_ref::set_slice(vhdl_expr *s, int w)
|
|
|
|
|
{
|
|
|
|
|
assert(type_);
|
2008-07-17 14:41:44 +02:00
|
|
|
|
2008-07-07 22:19:59 +02:00
|
|
|
slice_ = s;
|
|
|
|
|
slice_width_ = w;
|
2008-07-17 14:41:44 +02:00
|
|
|
|
|
|
|
|
vhdl_type_name_t tname = type_->get_name();
|
|
|
|
|
if (tname == VHDL_TYPE_ARRAY) {
|
|
|
|
|
type_ = new vhdl_type(*type_->get_base());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
assert(tname == VHDL_TYPE_UNSIGNED || tname == VHDL_TYPE_SIGNED);
|
2008-07-07 22:19:59 +02:00
|
|
|
|
2008-07-17 14:41:44 +02:00
|
|
|
if (type_)
|
|
|
|
|
delete type_;
|
|
|
|
|
|
|
|
|
|
if (w > 0)
|
|
|
|
|
type_ = new vhdl_type(tname, w);
|
|
|
|
|
else
|
|
|
|
|
type_ = vhdl_type::std_logic();
|
|
|
|
|
}
|
2008-07-07 22:19:59 +02:00
|
|
|
}
|
2008-07-17 14:41:44 +02:00
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_var_ref::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
of << name_;
|
2008-06-21 17:17:44 +02:00
|
|
|
if (slice_) {
|
|
|
|
|
of << "(";
|
2008-07-07 17:11:45 +02:00
|
|
|
if (slice_width_ > 0) {
|
|
|
|
|
slice_->emit(of, level);
|
|
|
|
|
of << " + " << slice_width_ << " downto ";
|
|
|
|
|
}
|
2008-06-21 17:17:44 +02:00
|
|
|
slice_->emit(of, level);
|
|
|
|
|
of << ")";
|
|
|
|
|
}
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_const_string::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
// In some instances a string literal can be ambiguous between
|
|
|
|
|
// a String type and some other types (e.g. std_logic_vector)
|
|
|
|
|
// The explicit cast to String removes this ambiguity (although
|
|
|
|
|
// isn't always strictly necessary)
|
|
|
|
|
of << "String'(\"" << value_ << "\")";
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_null_stmt::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
of << "null;";
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_fcall::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
of << name_;
|
|
|
|
|
exprs_.emit(of, level);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-18 13:51:11 +02:00
|
|
|
vhdl_abstract_assign_stmt::~vhdl_abstract_assign_stmt()
|
2008-06-12 12:24:43 +02:00
|
|
|
{
|
|
|
|
|
delete lhs_;
|
|
|
|
|
delete rhs_;
|
|
|
|
|
if (after_)
|
|
|
|
|
delete after_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_nbassign_stmt::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
|
|
|
|
lhs_->emit(of, level);
|
|
|
|
|
of << " <= ";
|
|
|
|
|
rhs_->emit(of, level);
|
2008-06-12 12:24:43 +02:00
|
|
|
|
|
|
|
|
if (after_) {
|
|
|
|
|
of << " after ";
|
|
|
|
|
after_->emit(of, level);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 14:27:48 +02:00
|
|
|
of << ";";
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_assign_stmt::emit(std::ostream &of, int level) const
|
2008-06-18 14:06:27 +02:00
|
|
|
{
|
|
|
|
|
lhs_->emit(of, level);
|
|
|
|
|
of << " := ";
|
|
|
|
|
rhs_->emit(of, level);
|
|
|
|
|
of << ";";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-23 15:28:27 +02:00
|
|
|
vhdl_const_bits::vhdl_const_bits(const char *value, int width, bool issigned)
|
|
|
|
|
: vhdl_expr(issigned ? vhdl_type::nsigned(width)
|
|
|
|
|
: vhdl_type::nunsigned(width), true),
|
|
|
|
|
qualified_(false),
|
|
|
|
|
signed_(issigned)
|
2008-06-23 16:00:55 +02:00
|
|
|
{
|
2008-06-16 15:26:38 +02:00
|
|
|
// Can't rely on value being NULL-terminated
|
|
|
|
|
while (width--)
|
|
|
|
|
value_.push_back(*value++);
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_const_bits::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-23 15:28:27 +02:00
|
|
|
if (qualified_)
|
|
|
|
|
of << (signed_ ? "signed" : "unsigned") << "'(\"";
|
|
|
|
|
else
|
|
|
|
|
of << "\"";
|
2008-06-08 14:27:48 +02:00
|
|
|
|
|
|
|
|
// The bits appear to be in reverse order
|
|
|
|
|
std::string::const_reverse_iterator it;
|
|
|
|
|
for (it = value_.rbegin(); it != value_.rend(); ++it)
|
2008-06-12 11:50:46 +02:00
|
|
|
of << vl_to_vhdl_bit(*it);
|
2008-06-08 14:27:48 +02:00
|
|
|
|
2008-06-23 13:14:12 +02:00
|
|
|
of << (qualified_ ? "\")" : "\"");
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_const_bit::emit(std::ostream &of, int level) const
|
2008-06-08 14:27:48 +02:00
|
|
|
{
|
2008-06-12 11:50:46 +02:00
|
|
|
of << "'" << vl_to_vhdl_bit(bit_) << "'";
|
2008-06-08 14:27:48 +02:00
|
|
|
}
|
2008-06-09 13:46:55 +02:00
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_const_int::emit(std::ostream &of, int level) const
|
2008-06-09 13:46:55 +02:00
|
|
|
{
|
|
|
|
|
of << value_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-27 19:39:16 +02:00
|
|
|
void vhdl_const_bool::emit(std::ostream &of, int level) const
|
|
|
|
|
{
|
|
|
|
|
of << (value_ ? "True" : "False");
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_const_time::emit(std::ostream &of, int level) const
|
2008-06-19 13:16:19 +02:00
|
|
|
{
|
|
|
|
|
of << value_;
|
|
|
|
|
switch (units_) {
|
|
|
|
|
case TIME_UNIT_NS:
|
|
|
|
|
of << " ns";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-09 15:21:55 +02:00
|
|
|
vhdl_cassign_stmt::~vhdl_cassign_stmt()
|
|
|
|
|
{
|
|
|
|
|
delete lhs_;
|
|
|
|
|
delete rhs_;
|
2008-07-14 20:00:58 +02:00
|
|
|
|
|
|
|
|
for (std::list<when_part_t>::const_iterator it = whens_.begin();
|
|
|
|
|
it != whens_.end();
|
|
|
|
|
++it) {
|
|
|
|
|
delete (*it).value;
|
|
|
|
|
delete (*it).cond;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vhdl_cassign_stmt::add_condition(vhdl_expr *value, vhdl_expr *cond)
|
|
|
|
|
{
|
|
|
|
|
when_part_t when = { value, cond };
|
|
|
|
|
whens_.push_back(when);
|
2008-06-09 15:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_cassign_stmt::emit(std::ostream &of, int level) const
|
2008-06-09 15:21:55 +02:00
|
|
|
{
|
|
|
|
|
lhs_->emit(of, level);
|
|
|
|
|
of << " <= ";
|
2008-07-14 20:00:58 +02:00
|
|
|
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 ";
|
|
|
|
|
}
|
2008-06-09 15:21:55 +02:00
|
|
|
rhs_->emit(of, level);
|
2008-07-23 14:40:42 +02:00
|
|
|
|
|
|
|
|
if (after_) {
|
|
|
|
|
of << " after ";
|
|
|
|
|
after_->emit(of, level);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-09 15:21:55 +02:00
|
|
|
of << ";";
|
|
|
|
|
}
|
2008-06-09 15:39:58 +02:00
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_assert_stmt::emit(std::ostream &of, int level) const
|
2008-06-11 14:37:21 +02:00
|
|
|
{
|
2008-06-12 21:26:23 +02:00
|
|
|
of << "assert false"; // TODO: Allow arbitrary expression
|
2008-06-11 14:37:21 +02:00
|
|
|
of << " report \"" << reason_ << "\" severity failure;";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-12 12:36:21 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-11 15:11:37 +02:00
|
|
|
vhdl_if_stmt::~vhdl_if_stmt()
|
|
|
|
|
{
|
|
|
|
|
delete test_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_if_stmt::emit(std::ostream &of, int level) const
|
2008-06-11 15:11:37 +02:00
|
|
|
{
|
|
|
|
|
of << "if ";
|
|
|
|
|
test_->emit(of, level);
|
|
|
|
|
of << " then";
|
|
|
|
|
then_part_.emit(of, level);
|
2008-06-16 20:53:42 +02:00
|
|
|
if (!else_part_.empty()) {
|
|
|
|
|
of << "else";
|
|
|
|
|
else_part_.emit(of, level);
|
|
|
|
|
}
|
2008-06-11 15:11:37 +02:00
|
|
|
of << "end if;";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-09 15:39:58 +02:00
|
|
|
vhdl_unaryop_expr::~vhdl_unaryop_expr()
|
|
|
|
|
{
|
|
|
|
|
delete operand_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_unaryop_expr::emit(std::ostream &of, int level) const
|
2008-06-09 15:39:58 +02:00
|
|
|
{
|
2008-07-04 12:17:24 +02:00
|
|
|
of << "(";
|
2008-06-09 15:39:58 +02:00
|
|
|
switch (op_) {
|
|
|
|
|
case VHDL_UNARYOP_NOT:
|
|
|
|
|
of << "not ";
|
|
|
|
|
break;
|
2008-07-22 16:44:29 +02:00
|
|
|
case VHDL_UNARYOP_NEG:
|
|
|
|
|
of << "-";
|
|
|
|
|
break;
|
2008-06-09 15:39:58 +02:00
|
|
|
}
|
|
|
|
|
operand_->emit(of, level);
|
2008-07-04 12:17:24 +02:00
|
|
|
of << ")";
|
2008-06-09 15:39:58 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-09 15:53:50 +02:00
|
|
|
vhdl_binop_expr::vhdl_binop_expr(vhdl_expr *left, vhdl_binop_t op,
|
|
|
|
|
vhdl_expr *right, vhdl_type *type)
|
|
|
|
|
: vhdl_expr(type), op_(op)
|
|
|
|
|
{
|
|
|
|
|
add_expr(left);
|
|
|
|
|
add_expr(right);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-09 15:39:58 +02:00
|
|
|
vhdl_binop_expr::~vhdl_binop_expr()
|
|
|
|
|
{
|
2008-06-09 15:53:50 +02:00
|
|
|
delete_children<vhdl_expr>(operands_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vhdl_binop_expr::add_expr(vhdl_expr *e)
|
|
|
|
|
{
|
|
|
|
|
operands_.push_back(e);
|
2008-06-09 15:39:58 +02:00
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_binop_expr::emit(std::ostream &of, int level) const
|
2008-06-09 15:39:58 +02:00
|
|
|
{
|
|
|
|
|
// Expressions are fully parenthesized to remove any
|
|
|
|
|
// ambiguity in the output
|
2008-06-09 15:53:50 +02:00
|
|
|
|
2008-06-09 15:39:58 +02:00
|
|
|
of << "(";
|
|
|
|
|
|
2008-06-09 15:53:50 +02:00
|
|
|
assert(operands_.size() > 0);
|
|
|
|
|
std::list<vhdl_expr*>::const_iterator it = operands_.begin();
|
|
|
|
|
|
2008-06-09 16:05:32 +02:00
|
|
|
(*it)->emit(of, level);
|
|
|
|
|
while (++it != operands_.end()) {
|
2008-06-24 15:58:58 +02:00
|
|
|
const char* ops[] = {
|
|
|
|
|
"and", "or", "=", "/=", "+", "-", "*", "<",
|
2008-08-01 18:42:26 +02:00
|
|
|
">", "<=", ">=", "sll", "srl", "xor", "&",
|
2008-08-07 15:18:26 +02:00
|
|
|
"nand", "nor", "xnor", "/", "mod", NULL
|
2008-06-24 15:58:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
of << " " << ops[op_] << " ";
|
2008-06-09 16:05:32 +02:00
|
|
|
|
|
|
|
|
(*it)->emit(of, level);
|
|
|
|
|
}
|
2008-06-09 15:39:58 +02:00
|
|
|
|
|
|
|
|
of << ")";
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-10 12:22:23 +02:00
|
|
|
vhdl_bit_spec_expr::~vhdl_bit_spec_expr()
|
|
|
|
|
{
|
|
|
|
|
delete others_;
|
|
|
|
|
|
|
|
|
|
std::list<bit_map>::iterator it;
|
|
|
|
|
for (it = bits_.begin(); it != bits_.end(); ++it)
|
|
|
|
|
delete (*it).e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
for (it = bits_.begin(); it != bits_.end(); ++it) {
|
|
|
|
|
of << (*it).bit << " => ";
|
|
|
|
|
(*it).e->emit(of, level);
|
|
|
|
|
of << ", ";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
of << "others => ";
|
|
|
|
|
others_->emit(of, level);
|
|
|
|
|
of << ")";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-21 16:03:36 +02:00
|
|
|
vhdl_case_branch::~vhdl_case_branch()
|
|
|
|
|
{
|
|
|
|
|
delete when_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_case_branch::emit(std::ostream &of, int level) const
|
2008-06-21 16:03:36 +02:00
|
|
|
{
|
|
|
|
|
of << "when ";
|
|
|
|
|
when_->emit(of, level);
|
|
|
|
|
of << " =>";
|
2008-07-23 15:31:41 +02:00
|
|
|
stmts_.emit(of, indent(level), false);
|
2008-06-21 16:03:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vhdl_case_stmt::~vhdl_case_stmt()
|
|
|
|
|
{
|
|
|
|
|
delete test_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_case_stmt::emit(std::ostream &of, int level) const
|
2008-06-21 16:03:36 +02:00
|
|
|
{
|
|
|
|
|
of << "case ";
|
|
|
|
|
test_->emit(of, level);
|
|
|
|
|
of << " is";
|
2008-06-21 17:28:07 +02:00
|
|
|
newline(of, indent(level));
|
|
|
|
|
|
|
|
|
|
case_branch_list_t::const_iterator it;
|
2008-07-23 15:31:41 +02:00
|
|
|
int n = branches_.size();
|
|
|
|
|
for (it = branches_.begin(); it != branches_.end(); ++it) {
|
2008-06-21 17:28:07 +02:00
|
|
|
(*it)->emit(of, level);
|
2008-07-23 15:31:41 +02:00
|
|
|
if (--n > 0)
|
|
|
|
|
newline(of, indent(level));
|
|
|
|
|
else
|
|
|
|
|
newline(of, level);
|
|
|
|
|
}
|
2008-06-21 17:28:07 +02:00
|
|
|
|
2008-06-21 16:03:36 +02:00
|
|
|
of << "end case;";
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-21 16:13:44 +02:00
|
|
|
vhdl_while_stmt::~vhdl_while_stmt()
|
|
|
|
|
{
|
|
|
|
|
delete test_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_while_stmt::emit(std::ostream &of, int level) const
|
2008-06-21 16:13:44 +02:00
|
|
|
{
|
|
|
|
|
of << "while ";
|
|
|
|
|
test_->emit(of, level);
|
2008-07-24 16:22:25 +02:00
|
|
|
of << " ";
|
|
|
|
|
vhdl_loop_stmt::emit(of, level);
|
2008-06-21 16:13:44 +02:00
|
|
|
}
|
2008-06-25 19:00:48 +02:00
|
|
|
|
2008-07-24 15:30:10 +02:00
|
|
|
void vhdl_loop_stmt::emit(std::ostream &of, int level) const
|
|
|
|
|
{
|
|
|
|
|
of << "loop";
|
|
|
|
|
stmts_.emit(of, level);
|
|
|
|
|
of << "end loop;";
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-24 15:52:06 +02:00
|
|
|
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 << " ";
|
2008-07-24 16:22:25 +02:00
|
|
|
vhdl_loop_stmt::emit(of, level);
|
2008-07-24 15:52:06 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-25 19:00:48 +02:00
|
|
|
vhdl_function::vhdl_function(const char *name, vhdl_type *ret_type)
|
|
|
|
|
: vhdl_decl(name, ret_type)
|
|
|
|
|
{
|
|
|
|
|
// A function contains two scopes:
|
|
|
|
|
// scope_ = The paramters
|
|
|
|
|
// variables_ = Local variables
|
|
|
|
|
// A call to get_scope returns variables_ whose parent is scope_
|
|
|
|
|
variables_.set_parent(&scope_);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_function::emit(std::ostream &of, int level) const
|
2008-06-25 19:00:48 +02:00
|
|
|
{
|
2008-07-31 22:17:49 +02:00
|
|
|
newline(of, level);
|
2008-08-03 15:46:57 +02:00
|
|
|
emit_comment(of, level);
|
2008-06-25 19:00:48 +02:00
|
|
|
of << "function " << name_ << " (";
|
2008-06-25 22:40:35 +02:00
|
|
|
emit_children<vhdl_decl>(of, scope_.get_decls(), level, ";");
|
|
|
|
|
of << ") ";
|
|
|
|
|
newline(of, level);
|
|
|
|
|
of << "return " << type_->get_string() << " is";
|
2008-06-25 19:00:48 +02:00
|
|
|
emit_children<vhdl_decl>(of, variables_.get_decls(), level);
|
|
|
|
|
of << "begin";
|
|
|
|
|
stmts_.emit(of, level);
|
2008-06-25 22:49:22 +02:00
|
|
|
of << " return Verilog_Result;";
|
|
|
|
|
newline(of, level);
|
2008-06-25 19:00:48 +02:00
|
|
|
of << "end function;";
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-03 11:50:31 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 11:37:22 +02:00
|
|
|
void vhdl_param_decl::emit(std::ostream &of, int level) const
|
2008-06-25 19:00:48 +02:00
|
|
|
{
|
|
|
|
|
of << name_ << " : ";
|
|
|
|
|
type_->emit(of, level);
|
|
|
|
|
}
|