1999-11-01 03:07:40 +01:00
|
|
|
/*
|
2010-10-10 06:35:57 +02:00
|
|
|
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
|
1999-11-01 03:07:40 +01:00
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
1999-12-01 07:06:16 +01:00
|
|
|
# include "functor.h"
|
|
|
|
|
# include "netlist.h"
|
|
|
|
|
|
2000-04-12 22:02:52 +02:00
|
|
|
/*
|
|
|
|
|
* This functor scans the behavioral code, looking for expressions to
|
|
|
|
|
* synthesize. Although it uses the proc_match_t class, it doesn't
|
|
|
|
|
* actually match anything, but transforms expressions into structural
|
|
|
|
|
* netlists. The product of this should be a process where all the
|
|
|
|
|
* expressions have been reduced to a signal ident, which references
|
|
|
|
|
* the NetNet of the now synthesized expression.
|
|
|
|
|
*/
|
|
|
|
|
class do_expr : public proc_match_t {
|
|
|
|
|
|
|
|
|
|
public:
|
2008-08-11 03:22:34 +02:00
|
|
|
do_expr(Design*d, NetScope*s)
|
|
|
|
|
: des_(d), scope_(s) { }
|
2000-04-12 22:02:52 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
Design*des_;
|
2008-08-11 03:22:34 +02:00
|
|
|
NetScope*scope_;
|
2000-04-12 22:02:52 +02:00
|
|
|
|
|
|
|
|
virtual int assign(NetAssign*);
|
2000-11-22 22:18:42 +01:00
|
|
|
virtual int assign_nb(NetAssignNB*);
|
2000-04-12 22:02:52 +02:00
|
|
|
virtual int event_wait(NetEvWait*);
|
2000-04-17 00:57:34 +02:00
|
|
|
virtual int condit(NetCondit*);
|
2000-04-12 22:02:52 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int do_expr::assign(NetAssign*stmt)
|
|
|
|
|
{
|
|
|
|
|
if (dynamic_cast<NetESignal*>(stmt->rval()))
|
|
|
|
|
return 0;
|
|
|
|
|
|
2008-12-22 22:48:34 +01:00
|
|
|
NetNet*tmp = stmt->rval()->synthesize(des_, scope_, stmt->rval());
|
2000-04-12 22:02:52 +02:00
|
|
|
if (tmp == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
NetESignal*tmpe = new NetESignal(tmp);
|
|
|
|
|
stmt->set_rval(tmpe);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-22 22:18:42 +01:00
|
|
|
int do_expr::assign_nb(NetAssignNB*stmt)
|
|
|
|
|
{
|
|
|
|
|
if (dynamic_cast<NetESignal*>(stmt->rval()))
|
|
|
|
|
return 0;
|
|
|
|
|
|
2008-12-22 22:48:34 +01:00
|
|
|
NetNet*tmp = stmt->rval()->synthesize(des_, scope_, stmt->rval());
|
2000-11-22 22:18:42 +01:00
|
|
|
if (tmp == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
NetESignal*tmpe = new NetESignal(tmp);
|
|
|
|
|
stmt->set_rval(tmpe);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 00:57:34 +02:00
|
|
|
int do_expr::condit(NetCondit*stmt)
|
|
|
|
|
{
|
|
|
|
|
/* synthesize the condition expression, if necessary. */
|
|
|
|
|
if (! dynamic_cast<NetESignal*>(stmt->expr())) {
|
2008-12-22 22:48:34 +01:00
|
|
|
NetNet*tmp = stmt->expr()->synthesize(des_, scope_, stmt->expr());
|
2000-04-17 00:57:34 +02:00
|
|
|
|
|
|
|
|
if (tmp) {
|
|
|
|
|
NetESignal*tmpe = new NetESignal(tmp);
|
|
|
|
|
stmt->set_expr(tmpe);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now recurse through the if and else clauses. */
|
|
|
|
|
if (NetProc*tmp = stmt->if_clause())
|
|
|
|
|
tmp->match_proc(this);
|
|
|
|
|
|
|
|
|
|
if (NetProc*tmp = stmt->else_clause())
|
|
|
|
|
tmp->match_proc(this);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-12 22:02:52 +02:00
|
|
|
int do_expr::event_wait(NetEvWait*stmt)
|
|
|
|
|
{
|
|
|
|
|
NetProc*tmp = stmt->statement();
|
|
|
|
|
if (tmp)
|
|
|
|
|
return tmp->match_proc(this);
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-01 07:06:16 +01:00
|
|
|
class synth_f : public functor_t {
|
1999-11-01 03:07:40 +01:00
|
|
|
|
1999-12-01 07:06:16 +01:00
|
|
|
public:
|
2010-10-10 06:35:57 +02:00
|
|
|
synth_f() { top_ = NULL; }
|
1999-12-01 07:06:16 +01:00
|
|
|
void process(class Design*, class NetProcTop*);
|
1999-11-01 03:07:40 +01:00
|
|
|
|
1999-12-01 07:06:16 +01:00
|
|
|
private:
|
|
|
|
|
void proc_always_(class Design*);
|
2000-05-13 22:55:47 +02:00
|
|
|
void proc_initial_(class Design*);
|
1999-11-01 03:07:40 +01:00
|
|
|
|
1999-12-01 07:06:16 +01:00
|
|
|
NetProcTop*top_;
|
|
|
|
|
};
|
1999-11-01 03:07:40 +01:00
|
|
|
|
|
|
|
|
|
1999-12-01 07:06:16 +01:00
|
|
|
/*
|
|
|
|
|
* Look at a process, and divide the problem into always and initial
|
|
|
|
|
* threads.
|
|
|
|
|
*/
|
|
|
|
|
void synth_f::process(class Design*des, class NetProcTop*top)
|
|
|
|
|
{
|
2000-05-13 22:55:47 +02:00
|
|
|
top_ = top;
|
1999-12-01 07:06:16 +01:00
|
|
|
switch (top->type()) {
|
2008-10-22 07:15:49 +02:00
|
|
|
case IVL_PR_ALWAYS:
|
1999-12-01 07:06:16 +01:00
|
|
|
proc_always_(des);
|
1999-11-01 03:07:40 +01:00
|
|
|
break;
|
2008-10-22 07:15:49 +02:00
|
|
|
case IVL_PR_INITIAL:
|
2000-05-13 22:55:47 +02:00
|
|
|
proc_initial_(des);
|
|
|
|
|
break;
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
1999-12-01 07:06:16 +01:00
|
|
|
}
|
1999-11-01 03:07:40 +01:00
|
|
|
|
1999-12-01 07:06:16 +01:00
|
|
|
void synth_f::proc_always_(class Design*des)
|
|
|
|
|
{
|
2008-08-11 03:22:34 +02:00
|
|
|
do_expr expr_pat(des, top_->scope());
|
2000-04-12 22:02:52 +02:00
|
|
|
top_->statement()->match_proc(&expr_pat);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-13 22:55:47 +02:00
|
|
|
void synth_f::proc_initial_(class Design*des)
|
|
|
|
|
{
|
2008-08-11 03:22:34 +02:00
|
|
|
do_expr expr_pat(des, top_->scope());
|
2000-05-13 22:55:47 +02:00
|
|
|
top_->statement()->match_proc(&expr_pat);
|
|
|
|
|
}
|
1999-12-01 07:06:16 +01:00
|
|
|
|
1999-11-01 03:07:40 +01:00
|
|
|
void synth(Design*des)
|
|
|
|
|
{
|
|
|
|
|
synth_f synth_obj;
|
|
|
|
|
des->functor(&synth_obj);
|
|
|
|
|
}
|