Pretty-print VHDL output
This commit is contained in:
parent
e178baefbd
commit
e38494a10c
|
|
@ -23,6 +23,26 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
static int g_errors = 0; // Total number of errors encountered
|
||||
|
||||
/*
|
||||
* Called when an unrecoverable problem is encountered.
|
||||
*/
|
||||
void error(const char *fmt, ...)
|
||||
{
|
||||
std::va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
std::printf("VHDL conversion error: "); // Source/line number?
|
||||
std::vprintf(fmt, args);
|
||||
std::putchar('\n');
|
||||
va_end(args);
|
||||
|
||||
g_errors++;
|
||||
}
|
||||
|
||||
extern "C" int target_design(ivl_design_t des)
|
||||
{
|
||||
|
|
@ -40,11 +60,15 @@ extern "C" int target_design(ivl_design_t des)
|
|||
// Dummy output to test regression script
|
||||
vhdl_entity test_ent(scope_name);
|
||||
vhdl_arch test_arch(scope_name);
|
||||
vhdl_process test_proc;
|
||||
test_arch.set_comment("I am a comment");
|
||||
test_arch.add_stmt(&test_proc);
|
||||
test_proc.set_comment("I am a process");
|
||||
test_ent.emit(outfile);
|
||||
test_arch.emit(outfile);
|
||||
}
|
||||
|
||||
outfile.close();
|
||||
|
||||
return 0;
|
||||
return g_errors;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,68 @@
|
|||
|
||||
#include "vhdl_element.hh"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
//////// HELPER FUNCTIONS ////////
|
||||
|
||||
static const int VHDL_INDENT = 2; // Spaces to indent
|
||||
|
||||
static int indent(int level)
|
||||
{
|
||||
return level + VHDL_INDENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emit a newline and indent to the correct level.
|
||||
*/
|
||||
static void newline(std::ofstream &of, int level)
|
||||
{
|
||||
of << std::endl;
|
||||
while (level--)
|
||||
of << ' ';
|
||||
}
|
||||
|
||||
static void blank_line(std::ofstream &of, int level)
|
||||
{
|
||||
of << std::endl;
|
||||
newline(of, level);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void emit_children(std::ofstream &of,
|
||||
const std::list<T*> &children,
|
||||
int level)
|
||||
{
|
||||
// Don't indent if there are no children
|
||||
if (children.size() == 0)
|
||||
newline(of, level);
|
||||
else {
|
||||
typename std::list<T*>::const_iterator it;
|
||||
for (it = children.begin(); it != children.end(); ++it) {
|
||||
newline(of, indent(level));
|
||||
(*it)->emit(of, indent(level));
|
||||
}
|
||||
newline(of, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////// ALL ELEMENTS ////////
|
||||
|
||||
void vhdl_element::set_comment(std::string comment)
|
||||
{
|
||||
comment_ = comment;
|
||||
}
|
||||
|
||||
void vhdl_element::emit_comment(std::ofstream &of, int level) const
|
||||
{
|
||||
if (comment_.size() > 0) {
|
||||
of << "-- " << comment_;
|
||||
newline(of, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////// ENTITY ////////
|
||||
|
||||
|
|
@ -29,11 +91,15 @@ vhdl_entity::vhdl_entity(const char *name)
|
|||
|
||||
}
|
||||
|
||||
void vhdl_entity::emit(std::ofstream &of)
|
||||
void vhdl_entity::emit(std::ofstream &of, int level) const
|
||||
{
|
||||
of << "entity " << name_ << " is" << std::endl;
|
||||
emit_comment(of, level);
|
||||
of << "entity " << name_ << " is";
|
||||
// ...ports...
|
||||
of << "end entity; " << std::endl;
|
||||
// newline(indent(level));
|
||||
newline(of, level);
|
||||
of << "end entity; ";
|
||||
blank_line(of, level); // Extra blank line after entities
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -45,12 +111,52 @@ vhdl_arch::vhdl_arch(const char *entity, const char *name)
|
|||
|
||||
}
|
||||
|
||||
void vhdl_arch::emit(std::ofstream &of)
|
||||
void vhdl_arch::add_stmt(vhdl_conc_stmt* stmt)
|
||||
{
|
||||
of << "architecture " << name_ << " of " << entity_;
|
||||
of << " is" << std::endl;
|
||||
// ...declarations...
|
||||
of << "begin" << std::endl;
|
||||
// ...statements...
|
||||
of << "end architecture;" << std::endl;
|
||||
stmts_.push_back(stmt);
|
||||
}
|
||||
|
||||
void vhdl_arch::emit(std::ofstream &of, int level) const
|
||||
{
|
||||
emit_comment(of, level);
|
||||
of << "architecture " << name_ << " of " << entity_;
|
||||
of << " is";
|
||||
// ...declarations...
|
||||
// newline(indent(level));
|
||||
newline(of, level);
|
||||
of << "begin";
|
||||
emit_children<vhdl_conc_stmt>(of, stmts_, level);
|
||||
of << "end architecture;";
|
||||
blank_line(of, level); // Extra blank line after architectures;
|
||||
}
|
||||
|
||||
|
||||
//////// PROCESS ////////
|
||||
|
||||
vhdl_process::vhdl_process(const char *name)
|
||||
: name_(name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void vhdl_process::add_stmt(vhdl_seq_stmt* stmt)
|
||||
{
|
||||
stmts_.push_back(stmt);
|
||||
}
|
||||
|
||||
void vhdl_process::emit(std::ofstream &of, int level) const
|
||||
{
|
||||
emit_comment(of, level);
|
||||
if (name_)
|
||||
of << name_ << ": ";
|
||||
of << "process is"; // TODO: sensitivity
|
||||
newline(of, level);
|
||||
// ...declarations...
|
||||
of << "begin";
|
||||
newline(of, level);
|
||||
// ...statements...
|
||||
of << "wait;"; // Just to stop the simulation hanging
|
||||
newline(of, level);
|
||||
of << "end process;";
|
||||
newline(of, level);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,28 +22,64 @@
|
|||
#define INC_VHDL_ELEMENT_HH
|
||||
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
|
||||
class vhdl_element;
|
||||
typedef std::list<vhdl_element*> element_list_t;
|
||||
|
||||
class vhdl_element {
|
||||
public:
|
||||
virtual void emit(std::ofstream &of) = 0;
|
||||
public:
|
||||
virtual void emit(std::ofstream &of, int level=0) const = 0;
|
||||
|
||||
void set_comment(std::string comment);
|
||||
protected:
|
||||
void emit_comment(std::ofstream &of, int level) const;
|
||||
private:
|
||||
std::string comment_;
|
||||
};
|
||||
|
||||
class vhdl_entity : public vhdl_element {
|
||||
public:
|
||||
vhdl_entity(const char *name);
|
||||
|
||||
void emit(std::ofstream &of);
|
||||
void emit(std::ofstream &of, int level=0) const;
|
||||
private:
|
||||
const char *name_;
|
||||
};
|
||||
|
||||
class vhdl_conc_stmt : public vhdl_element {
|
||||
};
|
||||
|
||||
typedef std::list<vhdl_conc_stmt*> conc_stmt_list_t;
|
||||
|
||||
class vhdl_seq_stmt : public vhdl_element {
|
||||
};
|
||||
|
||||
typedef std::list<vhdl_seq_stmt*> seq_stmt_list_t;
|
||||
|
||||
class vhdl_process : public vhdl_conc_stmt {
|
||||
public:
|
||||
vhdl_process(const char *name = NULL);
|
||||
|
||||
void emit(std::ofstream &of, int level) const;
|
||||
void add_stmt(vhdl_seq_stmt* stmt);
|
||||
private:
|
||||
seq_stmt_list_t stmts_;
|
||||
const char *name_;
|
||||
};
|
||||
|
||||
class vhdl_arch : public vhdl_element {
|
||||
public:
|
||||
vhdl_arch(const char *entity, const char *name="Behavioural");
|
||||
|
||||
void emit(std::ofstream &of);
|
||||
void emit(std::ofstream &of, int level=0) const;
|
||||
void add_stmt(vhdl_conc_stmt* stmt);
|
||||
private:
|
||||
conc_stmt_list_t stmts_;
|
||||
const char *name_, *entity_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -4,5 +4,7 @@
|
|||
#include "vhdl_config.h"
|
||||
#include "ivl_target.h"
|
||||
|
||||
void error(const char *fmt, ...);
|
||||
|
||||
#endif /* #ifndef INC_VHDL_TARGET_H */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue