From 13aaaab7839a16c98eaae635166dd238045b8c2d Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 6 Nov 2008 21:31:34 -0800 Subject: [PATCH] Bring analog contribution statements to the ivl_target API. Add support for analog processes with analog contributation statements all the way down to the ivl_target code generator API. --- Makefile.in | 2 +- emit.cc | 9 +++-- ivl.def | 2 + ivl_target.h | 27 +++++++++++--- net_analog.cc | 10 +++++ netlist.cc | 22 ++++++++++- netlist.h | 4 ++ t-dll-analog.cc | 87 ++++++++++++++++++++++++++++++++++++++++++++ t-dll-api.cc | 18 +++++++++ t-dll-proc.cc | 1 + t-dll.h | 10 ++++- target.cc | 19 +++++++++- target.h | 2 + tgt-stub/statement.c | 6 +++ tgt-stub/stub.c | 10 ++++- 15 files changed, 214 insertions(+), 15 deletions(-) create mode 100644 t-dll-analog.cc diff --git a/Makefile.in b/Makefile.in index 5e1a59a3d..6441c8983 100644 --- a/Makefile.in +++ b/Makefile.in @@ -113,7 +113,7 @@ distclean: clean rm -f Makefile config.status config.log config.cache config.h rm -f _pli_types.h -TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o +TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o O = main.o async.o design_dump.o discipline.o dup_expr.o \ diff --git a/emit.cc b/emit.cc index 89c8d6703..deb4b1a0e 100644 --- a/emit.cc +++ b/emit.cc @@ -192,9 +192,7 @@ bool NetProcTop::emit(struct target_t*tgt) const bool NetAnalogTop::emit(struct target_t*tgt) const { - cerr << get_fileline() << ": sorry: " - << "I don't know how to emit for analog processes." << endl; - return false; + return tgt->process(this); } bool NetProc::emit_proc(struct target_t*tgt) const @@ -241,6 +239,11 @@ bool NetCondit::emit_proc(struct target_t*tgt) const return tgt->proc_condit(this); } +bool NetContribution::emit_proc(struct target_t*tgt) const +{ + return tgt->proc_contribution(this); +} + bool NetDeassign::emit_proc(struct target_t*tgt) const { return tgt->proc_deassign(this); diff --git a/ivl.def b/ivl.def index c05ec3196..890876bc0 100644 --- a/ivl.def +++ b/ivl.def @@ -196,6 +196,7 @@ ivl_signal_width ivl_path_delay ivl_path_source +ivl_process_analog ivl_process_attr_cnt ivl_process_attr_val ivl_process_file @@ -221,6 +222,7 @@ ivl_stmt_delay_val ivl_stmt_events ivl_stmt_file ivl_stmt_lineno +ivl_stmt_lexp ivl_stmt_lval ivl_stmt_lvals ivl_stmt_lwidth diff --git a/ivl_target.h b/ivl_target.h index b21987158..f39b51d87 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -361,6 +361,7 @@ typedef enum ivl_statement_type_e { IVL_ST_CASEZ = 7, IVL_ST_CASSIGN = 8, IVL_ST_CONDIT = 9, + IVL_ST_CONTRIB = 27, IVL_ST_DEASSIGN = 10, IVL_ST_DELAY = 11, IVL_ST_DELAYX = 12, @@ -1718,12 +1719,16 @@ extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx); * is translated into a type and a single statement. (The statement * may be a compound statement.) * - * The ivl_process_type function gets the type of the process, - * an "initial" or "always" statement. + * ivl_process_type + * ivl_process_analog + * The ivl_process_type function returns the type of the process, + * an "initial" or "always" statement. The ivl_process_analog + * returns true if the process is analog. * - * A process is placed in a scope. The statement within the process - * operates within the scope of the process unless there are calls - * outside the scope. + * ivl_process_scope + * A process is placed in a scope. The statement within the process + * operates within the scope of the process unless there are calls + * outside the scope. * * The ivl_process_stmt function gets the statement that forms the * process. See the statement related functions for how to manipulate @@ -1733,6 +1738,7 @@ extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx); * attr_val methods return those attributes. */ extern ivl_process_type_t ivl_process_type(ivl_process_t net); +extern int ivl_process_analog(ivl_process_t net); extern ivl_scope_t ivl_process_scope(ivl_process_t net); @@ -1828,6 +1834,12 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net); * that constant value. If the expression is non-constant, the code * generator is supposed to know what to do about that, too. * + * - IVL_ST_CONTRIB + * This is an analog contribution statement. The ivl_stmt_lexp + * function returns the l-value expression which is guaranteed to be a + * branch access expression. The ivl_stmt_rval returns the r-value + * expression for the assignment. + * * - IVL_ST_DELAY, IVL_ST_DELAYX * These statement types are delay statements. They are a way to * attach a delay to a statement. The ivl_stmt_sub_stmt() function @@ -1893,6 +1905,8 @@ extern uint64_t ivl_stmt_delay_val(ivl_statement_t net); /* IVL_ST_WAIT IVL_ST_TRIGGER */ extern unsigned ivl_stmt_nevent(ivl_statement_t net); extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx); + /* IVL_ST_CONTRIB */ +extern ivl_expr_t ivl_stmt_lexp(ivl_statement_t net); /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_DEASSIGN IVL_ST_FORCE IVL_ST_RELEASE */ extern ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx); @@ -1907,7 +1921,8 @@ extern const char* ivl_stmt_name(ivl_statement_t net); extern ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx); /* IVL_ST_STASK */ extern unsigned ivl_stmt_parm_count(ivl_statement_t net); - /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_FORCE */ + /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_CONTRIB + IVL_ST_FORCE */ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net); /* IVL_ST_DELAY, IVL_ST_DELAYX, IVL_ST_FOREVER, IVL_ST_REPEAT IVL_ST_WAIT, IVL_ST_WHILE */ diff --git a/net_analog.cc b/net_analog.cc index f0b7d4ad2..9482aa7f4 100644 --- a/net_analog.cc +++ b/net_analog.cc @@ -35,3 +35,13 @@ NetContribution::NetContribution(NetEAccess*l, NetExpr*r) NetContribution::~NetContribution() { } + +const NetEAccess* NetContribution::lval() const +{ + return lval_; +} + +const NetExpr* NetContribution::rval() const +{ + return rval_; +} diff --git a/netlist.cc b/netlist.cc index 072112256..764cb514a 100644 --- a/netlist.cc +++ b/netlist.cc @@ -874,6 +874,11 @@ NetScope* NetProcTop::scope() return scope_; } +const NetScope* NetProcTop::scope() const +{ + return scope_; +} + NetAnalogTop::NetAnalogTop(NetScope*scope, ivl_process_type_t t, NetProc*st) : type_(t), statement_(st), scope_(scope) { @@ -884,7 +889,22 @@ NetAnalogTop::~NetAnalogTop() { } -const NetScope* NetProcTop::scope() const +NetProc* NetAnalogTop::statement() +{ + return statement_; +} + +const NetProc* NetAnalogTop::statement() const +{ + return statement_; +} + +NetScope* NetAnalogTop::scope() +{ + return scope_; +} + +const NetScope* NetAnalogTop::scope() const { return scope_; } diff --git a/netlist.h b/netlist.h index 5fc544640..d7aba331b 100644 --- a/netlist.h +++ b/netlist.h @@ -2439,6 +2439,10 @@ class NetContribution : public NetProc { explicit NetContribution(NetEAccess*lval, NetExpr*rval); ~NetContribution(); + const NetEAccess* lval() const; + const NetExpr* rval() const; + + virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; private: diff --git a/t-dll-analog.cc b/t-dll-analog.cc new file mode 100644 index 000000000..ff0f8c43b --- /dev/null +++ b/t-dll-analog.cc @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2008 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form 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.will need a Picture Elements Binary Software + * License. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "config.h" + +# include + +# include +# include "target.h" +# include "ivl_target.h" +# include "compiler.h" +# include "t-dll.h" +#ifdef HAVE_MALLOC_H +# include +#endif +# include + +bool dll_target::process(const NetAnalogTop*net) +{ + bool rc_flag = true; + + ivl_process_t obj = (struct ivl_process_s*) + calloc(1, sizeof(struct ivl_process_s)); + + obj->type_ = net->type(); + obj->analog_flag = 1; + + FILE_NAME(obj, net); + + /* Save the scope of the process. */ + obj->scope_ = lookup_scope_(net->scope()); + + obj->nattr = net->attr_cnt(); + obj->attr = fill_in_attributes(net); + + assert(stmt_cur_ == 0); + stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_); + assert(stmt_cur_); + rc_flag = net->statement()->emit_proc(this) && rc_flag; + + assert(stmt_cur_); + obj->stmt_ = stmt_cur_; + stmt_cur_ = 0; + + /* Save the process in the design. */ + obj->next_ = des_.threads_; + des_.threads_ = obj; + + return rc_flag; +} + +bool dll_target::proc_contribution(const NetContribution*net) +{ + assert(stmt_cur_); + assert(stmt_cur_->type_ == IVL_ST_NONE); + FILE_NAME(stmt_cur_, net); + + stmt_cur_->type_ = IVL_ST_CONTRIB; + + assert(expr_ == 0); + net->lval()->expr_scan(this); + stmt_cur_->u_.contrib_.lval = expr_; + expr_ = 0; + + net->rval()->expr_scan(this); + stmt_cur_->u_.contrib_.rval = expr_; + expr_ = 0; + + return true; +} diff --git a/t-dll-api.cc b/t-dll-api.cc index 6dce44632..c8f4e9f0e 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1478,6 +1478,11 @@ extern "C" ivl_process_type_t ivl_process_type(ivl_process_t net) return net->type_; } +extern "C" int ivl_process_analog(ivl_process_t net) +{ + return net->analog_flag != 0; +} + extern "C" ivl_scope_t ivl_process_scope(ivl_process_t net) { return net->scope_; @@ -2112,6 +2117,17 @@ extern "C" ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx) return 0; } +extern "C" ivl_expr_t ivl_stmt_lexp(ivl_statement_t net) +{ + switch (net->type_) { + case IVL_ST_CONTRIB: + return net->u_.contrib_.lval; + default: + assert(0); + } + return 0; +} + extern "C" ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx) { switch (net->type_) { @@ -2225,6 +2241,8 @@ extern "C" ivl_expr_t ivl_stmt_rval(ivl_statement_t net) case IVL_ST_CASSIGN: case IVL_ST_FORCE: return net->u_.assign_.rval_; + case IVL_ST_CONTRIB: + return net->u_.contrib_.rval; default: assert(0); } diff --git a/t-dll-proc.cc b/t-dll-proc.cc index 13ac6240f..21be53600 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -40,6 +40,7 @@ bool dll_target::process(const NetProcTop*net) calloc(1, sizeof(struct ivl_process_s)); obj->type_ = net->type(); + obj->analog_flag = 0; FILE_NAME(obj, net); diff --git a/t-dll.h b/t-dll.h index d5d149eb8..71be25c5d 100644 --- a/t-dll.h +++ b/t-dll.h @@ -102,6 +102,7 @@ struct dll_target : public target_t, public expr_scan_t { bool sign_extend(const NetSignExtend*); bool process(const NetProcTop*); + bool process(const NetAnalogTop*); void scope(const NetScope*); void signal(const NetNet*); bool signal_paths(const NetNet*); @@ -122,6 +123,7 @@ struct dll_target : public target_t, public expr_scan_t { void proc_case(const NetCase*); bool proc_cassign(const NetCAssign*); bool proc_condit(const NetCondit*); + bool proc_contribution(const NetContribution*); bool proc_deassign(const NetDeassign*); bool proc_delay(const NetPDelay*); bool proc_disable(const NetDisable*); @@ -553,7 +555,8 @@ struct ivl_parameter_s { * that generally only matters for VPI calls. */ struct ivl_process_s { - ivl_process_type_t type_; + ivl_process_type_t type_ : 2; + int analog_flag : 1; ivl_scope_t scope_; ivl_statement_t stmt_; perm_string file; @@ -707,6 +710,11 @@ struct ivl_statement_s { struct ivl_statement_s*stmt_; } condit_; + struct { /* IVL_ST_CONTRIB */ + ivl_expr_t lval; + ivl_expr_t rval; + } contrib_; + struct { /* IVL_ST_DELAY */ uint64_t delay_; ivl_statement_t stmt_; diff --git a/target.cc b/target.cc index 00bd9d0cb..cc33018ac 100644 --- a/target.cc +++ b/target.cc @@ -240,7 +240,16 @@ bool target_t::sign_extend(const NetSignExtend*net) bool target_t::process(const NetProcTop*top) { - return top->statement()->emit_proc(this); + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled process(NetProcTop)." << endl; + return false; +} + +bool target_t::process(const NetAnalogTop*top) +{ + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled process(NetAnalogTop)." << endl; + return false; } void target_t::proc_alloc(const NetAlloc*) @@ -292,6 +301,14 @@ bool target_t::proc_condit(const NetCondit*condit) return false; } +bool target_t::proc_contribution(const NetContribution*net) +{ + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled contribution:" << endl; + net->dump(cerr, 6); + return false; +} + bool target_t::proc_deassign(const NetDeassign*dev) { cerr << dev->get_fileline() << ": internal error: " diff --git a/target.h b/target.h index 2be4acf20..c62212086 100644 --- a/target.h +++ b/target.h @@ -103,6 +103,7 @@ struct target_t { /* Output a process (called for each process). It is up to the target to recurse if desired. */ virtual bool process(const NetProcTop*); + virtual bool process(const NetAnalogTop*); /* Various kinds of process nodes are dispatched through these. */ virtual void proc_alloc(const NetAlloc*); @@ -112,6 +113,7 @@ struct target_t { virtual void proc_case(const NetCase*); virtual bool proc_cassign(const NetCAssign*); virtual bool proc_condit(const NetCondit*); + virtual bool proc_contribution(const NetContribution*); virtual bool proc_deassign(const NetDeassign*); virtual bool proc_delay(const NetPDelay*); virtual bool proc_disable(const NetDisable*); diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index b7807bbcb..807c64e99 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -287,6 +287,12 @@ void show_statement(ivl_statement_t net, unsigned ind) break; } + case IVL_ST_CONTRIB: + fprintf(out, "%*sCONTRIBUTION ( <+ )\n", ind, ""); + show_expression(ivl_stmt_lexp(net), ind+4); + show_expression(ivl_stmt_rval(net), ind+4); + break; + case IVL_ST_DEASSIGN: fprintf(out, "%*sDEASSIGN \n", ind, "", ivl_stmt_lwidth(net)); diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 5e352dca3..a10154447 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -999,10 +999,16 @@ static int show_process(ivl_process_t net, void*x) switch (ivl_process_type(net)) { case IVL_PR_INITIAL: - fprintf(out, "initial\n"); + if (ivl_process_analog(net)) + fprintf(out, "analog initial\n"); + else + fprintf(out, "initial\n"); break; case IVL_PR_ALWAYS: - fprintf(out, "always\n"); + if (ivl_process_analog(net)) + fprintf(out, "analog\n"); + else + fprintf(out, "always\n"); break; }