From e38494a10c8d39579699ef6408c987847cf11895 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Thu, 29 May 2008 16:24:16 +0100 Subject: [PATCH] Pretty-print VHDL output --- tgt-vhdl/vhdl.cc | 26 +++++++- tgt-vhdl/vhdl_element.cc | 126 +++++++++++++++++++++++++++++++++++---- tgt-vhdl/vhdl_element.hh | 44 ++++++++++++-- tgt-vhdl/vhdl_target.h | 2 + 4 files changed, 183 insertions(+), 15 deletions(-) diff --git a/tgt-vhdl/vhdl.cc b/tgt-vhdl/vhdl.cc index bd9b0e052..91233122d 100644 --- a/tgt-vhdl/vhdl.cc +++ b/tgt-vhdl/vhdl.cc @@ -23,6 +23,26 @@ #include #include +#include +#include + +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; } diff --git a/tgt-vhdl/vhdl_element.cc b/tgt-vhdl/vhdl_element.cc index 4f703672f..c92c182b2 100644 --- a/tgt-vhdl/vhdl_element.cc +++ b/tgt-vhdl/vhdl_element.cc @@ -20,6 +20,68 @@ #include "vhdl_element.hh" +#include + + +//////// 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 +void emit_children(std::ofstream &of, + const std::list &children, + int level) +{ + // Don't indent if there are no children + if (children.size() == 0) + newline(of, level); + else { + typename std::list::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(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); } diff --git a/tgt-vhdl/vhdl_element.hh b/tgt-vhdl/vhdl_element.hh index 0cf19768f..b47fe843c 100644 --- a/tgt-vhdl/vhdl_element.hh +++ b/tgt-vhdl/vhdl_element.hh @@ -22,28 +22,64 @@ #define INC_VHDL_ELEMENT_HH #include +#include +#include + + +class vhdl_element; +typedef std::list 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 conc_stmt_list_t; + +class vhdl_seq_stmt : public vhdl_element { +}; + +typedef std::list 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 + diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index e40591fca..dc14b8f50 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -4,5 +4,7 @@ #include "vhdl_config.h" #include "ivl_target.h" +void error(const char *fmt, ...); + #endif /* #ifndef INC_VHDL_TARGET_H */