diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index bc4492231..1ff2f5031 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -25,6 +25,34 @@ #include #include +/* + * Given a nexus and an architecture, find the first signal + * that is connected to the nexus, if there is one. + */ +static vhdl_var_ref *nexus_to_var_ref(vhdl_arch *arch, ivl_nexus_t nexus) +{ + int nptrs = ivl_nexus_ptrs(nexus); + for (int i = 0; i < nptrs; i++) { + ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i); + + ivl_signal_t sig; + if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) { + const char *signame = ivl_signal_basename(sig); + + vhdl_decl *decl = arch->get_decl(signame); + assert(decl); + + vhdl_type *type = new vhdl_type(*(decl->get_type())); + return new vhdl_var_ref(signame, type); + } + else { + // Ignore other types of nexus pointer + } + } + + assert(false); +} + /* * Translate all the primitive logic gates into concurrent * signal assignments. @@ -35,6 +63,10 @@ static void declare_logic(vhdl_arch *arch, ivl_scope_t scope) for (int i = 0; i < nlogs; i++) { ivl_net_logic_t log = ivl_scope_log(scope, i); + // The output is always pin zero + ivl_nexus_t output = ivl_logic_pin(log, 0); + vhdl_var_ref *lhs = nexus_to_var_ref(arch, output); + switch (ivl_logic_type(log)) { case IVL_LO_NOT: break; diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index 9a9717156..bcd1751b9 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -455,3 +455,49 @@ void vhdl_cassign_stmt::emit(std::ofstream &of, int level) const rhs_->emit(of, level); of << ";"; } + +vhdl_unaryop_expr::~vhdl_unaryop_expr() +{ + delete operand_; +} + +void vhdl_unaryop_expr::emit(std::ofstream &of, int level) const +{ + switch (op_) { + case VHDL_UNARYOP_NOT: + of << "not "; + break; + } + operand_->emit(of, level); +} + +vhdl_binop_expr::~vhdl_binop_expr() +{ + delete left_; + delete right_; +} + +void vhdl_binop_expr::emit(std::ofstream &of, int level) const +{ + // Expressions are fully parenthesized to remove any + // ambiguity in the output + of << "("; + right_->emit(of, level); + + switch (op_) { + case VHDL_BINOP_AND: + of << " and "; + break; + case VHDL_BINOP_OR: + of << " or "; + break; + } + + right_->emit(of, level); + of << ")"; +} + + + + + diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 600bea11c..9b9c9a9cc 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -53,6 +53,43 @@ private: }; +enum vhdl_binop_t { + VHDL_BINOP_AND, + VHDL_BINOP_OR, +}; + +class vhdl_binop_expr : public vhdl_expr { +public: + vhdl_binop_expr(vhdl_expr *left, vhdl_binop_t op, + vhdl_expr *right, vhdl_type *type) + : vhdl_expr(type), left_(left), right_(right), op_(op) {} + ~vhdl_binop_expr(); + + void emit(std::ofstream &of, int level) const; +private: + vhdl_expr *left_, *right_; + vhdl_binop_t op_; +}; + + +enum vhdl_unaryop_t { + VHDL_UNARYOP_NOT, +}; + +class vhdl_unaryop_expr : public vhdl_expr { +public: + vhdl_unaryop_expr(vhdl_unaryop_t op, vhdl_expr *operand, + vhdl_type *type) + : vhdl_expr(type), op_(op), operand_(operand) {} + ~vhdl_unaryop_expr(); + + void emit(std::ofstream &of, int level) const; +private: + vhdl_unaryop_t op_; + vhdl_expr *operand_; +}; + + class vhdl_const_string : public vhdl_expr { public: vhdl_const_string(const char *value)