From e6fa72c3185aee5816dd12c206ba0d1da0056d73 Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 5 Mar 2007 05:59:10 +0000 Subject: [PATCH] Handle processes within generate loops. --- PGenerate.cc | 7 ++- PGenerate.h | 6 +- Statement.h | 7 ++- elab_lval.cc | 34 ++++++----- elab_scope.cc | 10 +++- elaborate.cc | 161 ++++++++++++++++++++++++++------------------------ pform.cc | 11 +++- pform_dump.cc | 10 +++- 8 files changed, 147 insertions(+), 99 deletions(-) diff --git a/PGenerate.cc b/PGenerate.cc index 272f5f1fb..ff3171a32 100644 --- a/PGenerate.cc +++ b/PGenerate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PGenerate.cc,v 1.1 2006/04/10 02:40:18 steve Exp $" +#ident "$Id: PGenerate.cc,v 1.2 2007/03/05 05:59:10 steve Exp $" #endif # include "PGenerate.h" @@ -55,3 +55,8 @@ void PGenerate::add_gate(PGate*gate) { gates.push_back(gate); } + +void PGenerate::add_behavior(PProcess*proc) +{ + behaviors.push_back(proc); +} diff --git a/PGenerate.h b/PGenerate.h index 9b5ef76fc..c913f87f5 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PGenerate.h,v 1.1 2006/04/10 02:40:18 steve Exp $" +#ident "$Id: PGenerate.h,v 1.2 2007/03/05 05:59:10 steve Exp $" #endif # include "LineInfo.h" @@ -31,6 +31,7 @@ class Design; class NetScope; class PExpr; +class PProcess; class PGate; class PWire; @@ -65,6 +66,9 @@ class PGenerate : public LineInfo { list gates; void add_gate(PGate*); + list behaviors; + void add_behavior(PProcess*behave); + // This method is called by the elaboration of a module to // generate scopes. the container is the scope that is to // contain the generated scope. diff --git a/Statement.h b/Statement.h index 7bb12116f..e29d89d59 100644 --- a/Statement.h +++ b/Statement.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: Statement.h,v 1.42 2005/12/05 21:21:18 steve Exp $" +#ident "$Id: Statement.h,v 1.43 2007/03/05 05:59:10 steve Exp $" #endif # include @@ -55,6 +55,8 @@ class PProcess : public LineInfo { virtual ~PProcess(); + bool elaborate(Design*des, NetScope*scope) const; + Type type() const { return type_; } Statement*statement() { return statement_; } @@ -458,6 +460,9 @@ class PWhile : public Statement { /* * $Log: Statement.h,v $ + * Revision 1.43 2007/03/05 05:59:10 steve + * Handle processes within generate loops. + * * Revision 1.42 2005/12/05 21:21:18 steve * Fixes for stubborn compilers. * diff --git a/elab_lval.cc b/elab_lval.cc index 23b874372..0e28f2c9e 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_lval.cc,v 1.40 2007/02/27 05:14:38 steve Exp $" +#ident "$Id: elab_lval.cc,v 1.41 2007/03/05 05:59:10 steve Exp $" #endif # include "config.h" @@ -27,6 +27,7 @@ # include "netmisc.h" # include "compiler.h" # include +# include "ivl_assert.h" /* * These methods generate a NetAssign_ object for the l-value of the @@ -198,8 +199,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, return 0; } - assert(msb_ == 0); - assert(lsb_ == 0); + ivl_assert(*this, msb_ == 0); + ivl_assert(*this, lsb_ == 0); long msb, lsb; NetExpr*mux; @@ -210,20 +211,20 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, as a part select with a bit width of 1. If the expression it not constant, then return the expression as a mux. */ - assert(idx_.size() == 1); - verinum*v = idx_[0]->eval_const(des, scope); - if (v == 0) { - NetExpr*m = idx_[0]->elaborate_expr(des, scope, -1, false); - assert(m); - msb = 0; - lsb = 0; - mux = m; + + ivl_assert(*this, idx_.size() == 1); + + NetExpr*index_expr = elab_and_eval(des, scope, idx_[0], -1); + + if (NetEConst*index_con = dynamic_cast (index_expr)) { + msb = index_con->value().as_long(); + lsb = index_con->value().as_long(); + mux = 0; } else { - - msb = v->as_long(); - lsb = v->as_long(); - mux = 0; + msb = 0; + lsb = 0; + mux = index_expr; } } else { @@ -465,6 +466,9 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const /* * $Log: elab_lval.cc,v $ + * Revision 1.41 2007/03/05 05:59:10 steve + * Handle processes within generate loops. + * * Revision 1.40 2007/02/27 05:14:38 steve * Detect and warn about lval array index out fo bounds. * diff --git a/elab_scope.cc b/elab_scope.cc index c06bc0d13..852f863e6 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_scope.cc,v 1.41 2006/06/02 04:48:50 steve Exp $" +#ident "$Id: elab_scope.cc,v 1.42 2007/03/05 05:59:10 steve Exp $" #endif # include "config.h" @@ -374,6 +374,11 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) loop_index, genvar_verinum); scope->set_localparam(loop_index, gp); + + if (debug_elaborate) + cerr << get_line() << ": debug: " + << "Create implicit localparam " + << loop_index << " = " << genvar_verinum << endl; } scope_list_.push_back(scope); @@ -748,6 +753,9 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const /* * $Log: elab_scope.cc,v $ + * Revision 1.42 2007/03/05 05:59:10 steve + * Handle processes within generate loops. + * * Revision 1.41 2006/06/02 04:48:50 steve * Make elaborate_expr methods aware of the width that the context * requires of it. In the process, fix sizing of the width of unary diff --git a/elaborate.cc b/elaborate.cc index 5314f0ccb..c37e28c30 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elaborate.cc,v 1.362 2007/03/03 05:56:55 steve Exp $" +#ident "$Id: elaborate.cc,v 1.363 2007/03/05 05:59:10 steve Exp $" #endif # include "config.h" @@ -2905,6 +2905,79 @@ NetProc* PWhile::elaborate(Design*des, NetScope*scope) const return loop; } +bool PProcess::elaborate(Design*des, NetScope*scope) const +{ + NetProc*cur = statement_->elaborate(des, scope); + if (cur == 0) { + return false; + } + + NetProcTop*top=0; + switch (type()) { + case PProcess::PR_INITIAL: + top = new NetProcTop(scope, NetProcTop::KINITIAL, cur); + break; + case PProcess::PR_ALWAYS: + top = new NetProcTop(scope, NetProcTop::KALWAYS, cur); + break; + } + ivl_assert(*this, top); + + // Evaluate the attributes for this process, if there + // are any. These attributes are to be attached to the + // NetProcTop object. + struct attrib_list_t*attrib_list = 0; + unsigned attrib_list_n = 0; + attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope); + + for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1) + top->attribute(attrib_list[adx].key, + attrib_list[adx].val); + + delete[]attrib_list; + + top->set_line(*this); + des->add_process(top); + + /* Detect the special case that this is a combinational + always block. We want to attach an _ivl_schedule_push + attribute to this process so that it starts up and + gets into its wait statement before non-combinational + code is executed. */ + do { + if (top->type() != NetProcTop::KALWAYS) + break; + + NetEvWait*st = dynamic_cast(top->statement()); + if (st == 0) + break; + + if (st->nevents() != 1) + break; + + NetEvent*ev = st->event(0); + + if (ev->nprobe() == 0) + break; + + bool anyedge_test = true; + for (unsigned idx = 0 ; anyedge_test && (idxnprobe()) + ; idx += 1) { + const NetEvProbe*pr = ev->probe(idx); + if (pr->edge() != NetEvProbe::ANYEDGE) + anyedge_test = false; + } + + if (! anyedge_test) + break; + + top->attribute(perm_string::literal("_ivl_schedule_push"), + verinum(1)); + } while (0); + + return true; +} + void PSpecPath::elaborate(Design*des, NetScope*scope) const { uint64_t delay_value[12]; @@ -3171,80 +3244,9 @@ bool Module::elaborate(Design*des, NetScope*scope) const const list&sl = get_behaviors(); for (list::const_iterator st = sl.begin() - ; st != sl.end() - ; st ++ ) { - - NetProc*cur = (*st)->statement()->elaborate(des, scope); - if (cur == 0) { - result_flag = false; - continue; - } - - NetProcTop*top=NULL; - switch ((*st)->type()) { - case PProcess::PR_INITIAL: - top = new NetProcTop(scope, NetProcTop::KINITIAL, cur); - break; - case PProcess::PR_ALWAYS: - top = new NetProcTop(scope, NetProcTop::KALWAYS, cur); - break; - } - assert(top); - - // Evaluate the attributes for this process, if there - // are any. These attributes are to be attached to the - // NetProcTop object. - struct attrib_list_t*attrib_list = 0; - unsigned attrib_list_n = 0; - attrib_list = evaluate_attributes((*st)->attributes, - attrib_list_n, - des, scope); - - for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1) - top->attribute(attrib_list[adx].key, - attrib_list[adx].val); - - delete[]attrib_list; - - top->set_line(*(*st)); - des->add_process(top); - - /* Detect the special case that this is a combinational - always block. We want to attach an _ivl_schedule_push - attribute to this process so that it starts up and - gets into its wait statement before non-combinational - code is executed. */ - do { - if (top->type() != NetProcTop::KALWAYS) - break; - - NetEvWait*st = dynamic_cast(top->statement()); - if (st == 0) - break; - - if (st->nevents() != 1) - break; - - NetEvent*ev = st->event(0); - - if (ev->nprobe() == 0) - break; - - bool anyedge_test = true; - for (unsigned idx = 0 ; anyedge_test && (idxnprobe()) - ; idx += 1) { - const NetEvProbe*pr = ev->probe(idx); - if (pr->edge() != NetEvProbe::ANYEDGE) - anyedge_test = false; - } - - if (! anyedge_test) - break; - - top->attribute(perm_string::literal("_ivl_schedule_push"), - verinum(1)); - } while (0); + ; st != sl.end() ; st ++ ) { + result_flag &= (*st)->elaborate(des, scope); } // Elaborate the specify paths of the module. @@ -3279,10 +3281,12 @@ bool PGenerate::elaborate(Design*des) const bool PGenerate::elaborate_(Design*des, NetScope*scope) const { typedef list::const_iterator gates_it_t; - for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ ) { - + for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ ) + (*cur)->elaborate(des, scope); + + typedef list::const_iterator proc_it_t; + for (proc_it_t cur = behaviors.begin(); cur != behaviors.end(); cur++) (*cur)->elaborate(des, scope); - } return true; } @@ -3396,6 +3400,9 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.363 2007/03/05 05:59:10 steve + * Handle processes within generate loops. + * * Revision 1.362 2007/03/03 05:56:55 steve * Check that path source/destination are ports. * diff --git a/pform.cc b/pform.cc index 59669fbd9..3320c42e9 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.cc,v 1.140 2007/02/12 01:52:21 steve Exp $" +#ident "$Id: pform.cc,v 1.141 2007/03/05 05:59:10 steve Exp $" #endif # include "config.h" @@ -1719,7 +1719,11 @@ PProcess* pform_make_behavior(PProcess::Type type, Statement*st, delete attr; } - pform_cur_module->add_behavior(pp); + if (pform_cur_generate) + pform_cur_generate->add_behavior(pp); + else + pform_cur_module->add_behavior(pp); + return pp; } @@ -1764,6 +1768,9 @@ int pform_parse(const char*path, FILE*file) /* * $Log: pform.cc,v $ + * Revision 1.141 2007/03/05 05:59:10 steve + * Handle processes within generate loops. + * * Revision 1.140 2007/02/12 01:52:21 steve * Parse all specify paths to pform. * diff --git a/pform_dump.cc b/pform_dump.cc index 0fc9ffbb5..1539069b0 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform_dump.cc,v 1.95 2007/02/12 01:52:21 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.96 2007/03/05 05:59:10 steve Exp $" #endif # include "config.h" @@ -819,6 +819,11 @@ void PGenerate::dump(ostream&out) const (*idx)->dump(out, 6); } + for (list::const_iterator idx = behaviors.begin() + ; idx != behaviors.end() ; idx++) { + (*idx)->dump(out, 6); + } + out << " endgenerate" << endl; } @@ -1024,6 +1029,9 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.96 2007/03/05 05:59:10 steve + * Handle processes within generate loops. + * * Revision 1.95 2007/02/12 01:52:21 steve * Parse all specify paths to pform. *