Elaborate task input ports.
This commit is contained in:
parent
9021f68996
commit
93a77a2efd
9
PTask.cc
9
PTask.cc
|
|
@ -17,13 +17,13 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PTask.cc,v 1.1 1999/07/03 02:12:51 steve Exp $"
|
||||
#ident "$Id: PTask.cc,v 1.2 1999/07/24 02:11:19 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PTask.h"
|
||||
|
||||
PTask::PTask(Statement*s)
|
||||
: statement_(s)
|
||||
PTask::PTask(svector<PWire*>*p, Statement*s)
|
||||
: ports_(p), statement_(s)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -33,6 +33,9 @@ PTask::~PTask()
|
|||
|
||||
/*
|
||||
* $Log: PTask.cc,v $
|
||||
* Revision 1.2 1999/07/24 02:11:19 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.1 1999/07/03 02:12:51 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
|
|
|
|||
10
PTask.h
10
PTask.h
|
|
@ -19,12 +19,14 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PTask.h,v 1.1 1999/07/03 02:12:51 steve Exp $"
|
||||
#ident "$Id: PTask.h,v 1.2 1999/07/24 02:11:19 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "svector.h"
|
||||
# include <string>
|
||||
class Design;
|
||||
class PWire;
|
||||
class Statement;
|
||||
|
||||
/*
|
||||
|
|
@ -33,13 +35,14 @@ class Statement;
|
|||
class PTask : public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PTask(Statement*s);
|
||||
explicit PTask(svector<PWire*>*p, Statement*s);
|
||||
~PTask();
|
||||
|
||||
virtual void elaborate(Design*des, const string&path) const;
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
svector<PWire*>*ports_;
|
||||
Statement*statement_;
|
||||
|
||||
private: // Not implemented
|
||||
|
|
@ -49,6 +52,9 @@ class PTask : public LineInfo {
|
|||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.2 1999/07/24 02:11:19 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.1 1999/07/03 02:12:51 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: design_dump.cc,v 1.32 1999/07/17 19:50:59 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.33 1999/07/24 02:11:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -196,7 +196,28 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
|
|||
void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "task " << name_ << ";" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
o << setw(ind+4) << "";
|
||||
switch (ports_[idx]->port_type()) {
|
||||
case NetNet::PINPUT:
|
||||
o << "input ";
|
||||
break;
|
||||
case NetNet::POUTPUT:
|
||||
o << "output ";
|
||||
break;
|
||||
case NetNet::PINOUT:
|
||||
o << "input ";
|
||||
break;
|
||||
default:
|
||||
o << "NOT_A_PORT ";
|
||||
break;
|
||||
}
|
||||
o << ports_[idx]->name() << ";" << endl;
|
||||
}
|
||||
|
||||
proc_->dump(o, ind+4);
|
||||
|
||||
o << setw(ind) << "" << "endtask" << endl;
|
||||
}
|
||||
|
||||
|
|
@ -480,22 +501,7 @@ void NetSTask::dump(ostream&o, unsigned ind) const
|
|||
|
||||
void NetUTask::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << task_->name();
|
||||
|
||||
if (parms_.count() > 0) {
|
||||
o << "(";
|
||||
if (parms_[0])
|
||||
parms_[0]->dump(o);
|
||||
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
o << ", ";
|
||||
if (parms_[idx])
|
||||
parms_[idx]->dump(o);
|
||||
}
|
||||
|
||||
o << ")";
|
||||
}
|
||||
o << ";" << endl;
|
||||
o << setw(ind) << "" << task_->name() << ";" << endl;
|
||||
}
|
||||
|
||||
void NetWhile::dump(ostream&o, unsigned ind) const
|
||||
|
|
@ -684,6 +690,9 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.33 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.32 1999/07/17 19:50:59 steve
|
||||
* netlist support for ternary operator.
|
||||
*
|
||||
|
|
|
|||
115
elaborate.cc
115
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: elaborate.cc,v 1.58 1999/07/18 21:17:50 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.59 1999/07/24 02:11:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -103,6 +103,8 @@ void PWire::elaborate(Design*des, const string&path) const
|
|||
NetNet::Type wtype = type_;
|
||||
if (wtype == NetNet::IMPLICIT)
|
||||
wtype = NetNet::WIRE;
|
||||
if (wtype == NetNet::IMPLICIT_REG)
|
||||
wtype = NetNet::REG;
|
||||
|
||||
unsigned wid = 1;
|
||||
|
||||
|
|
@ -1533,15 +1535,36 @@ NetProc* PCallTask::elaborate_sys(Design*des, const string&path) const
|
|||
return cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* A call to a user defined task is different from a call to a system
|
||||
* task because a user task in a netlist has no parameters: the
|
||||
* assignments are done by the calling thread. For example:
|
||||
*
|
||||
* task foo;
|
||||
* input a;
|
||||
* output b;
|
||||
* [...]
|
||||
* endtask;
|
||||
*
|
||||
* [...] foo(x, y);
|
||||
*
|
||||
* is really:
|
||||
*
|
||||
* task foo;
|
||||
* reg a;
|
||||
* reg b;
|
||||
* [...]
|
||||
* endtask;
|
||||
*
|
||||
* [...]
|
||||
* begin
|
||||
* a = x;
|
||||
* foo;
|
||||
* y = b;
|
||||
* end
|
||||
*/
|
||||
NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const
|
||||
{
|
||||
svector<NetExpr*>eparms (nparms());
|
||||
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
|
||||
PExpr*ex = parm(idx);
|
||||
eparms[idx] = ex? ex->elaborate_expr(des, path) : 0;
|
||||
}
|
||||
|
||||
NetTaskDef*def = des->find_task(path + "." + name_);
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": Enable of unknown task ``" <<
|
||||
|
|
@ -1550,8 +1573,60 @@ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetUTask*cur = new NetUTask(def, eparms);
|
||||
return cur;
|
||||
if (nparms() != def->port_count()) {
|
||||
cerr << get_line() << ": Port count mismatch in call to ``"
|
||||
<< name_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetUTask*cur;
|
||||
|
||||
/* Handle tasks with no parameters specially. There is no need
|
||||
to make a sequential block to hold the generated code. */
|
||||
if (nparms() == 0) {
|
||||
cur = new NetUTask(def);
|
||||
return cur;
|
||||
}
|
||||
|
||||
NetBlock*block = new NetBlock(NetBlock::SEQU);
|
||||
|
||||
/* Generate assignment statement statements for the input and
|
||||
INOUT ports of the task. */
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
|
||||
|
||||
NetNet*port = def->port(idx);
|
||||
assert(port->port_type() != NetNet::NOT_A_PORT);
|
||||
if (port->port_type() == NetNet::POUTPUT)
|
||||
continue;
|
||||
|
||||
NetExpr*rv = parms_[idx]->elaborate_expr(des, path);
|
||||
NetAssign*pr = new NetAssign("@", des, port->pin_count(), rv);
|
||||
for (unsigned pi = 0 ; pi < port->pin_count() ; pi += 1)
|
||||
connect(port->pin(pi), pr->pin(pi));
|
||||
des->add_node(pr);
|
||||
block->append(pr);
|
||||
}
|
||||
|
||||
/* Generate the task call proper... */
|
||||
cur = new NetUTask(def);
|
||||
block->append(cur);
|
||||
|
||||
/* Generate assignment statement statements for the output and
|
||||
INOUT ports of the task. */
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
|
||||
|
||||
NetNet*port = def->port(idx);
|
||||
assert(port->port_type() != NetNet::NOT_A_PORT);
|
||||
if (port->port_type() == NetNet::PINPUT)
|
||||
continue;
|
||||
|
||||
cerr << get_line() << ": Sorry, output ports not yet "
|
||||
"implemented." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
NetProc* PDelayStatement::elaborate(Design*des, const string&path) const
|
||||
|
|
@ -1725,7 +1800,9 @@ NetProc* PRepeat::elaborate(Design*des, const string&path) const
|
|||
|
||||
/*
|
||||
* A task definition is elaborated by elaborating the statement that
|
||||
* it contains, and ... XXXX
|
||||
* it contains, and connecting its ports to NetNet objects. The
|
||||
* netlist doesn't really need the array of parameters once elaboration
|
||||
* is complete, but this is the best place to store them.
|
||||
*/
|
||||
void PTask::elaborate(Design*des, const string&path) const
|
||||
{
|
||||
|
|
@ -1737,8 +1814,19 @@ void PTask::elaborate(Design*des, const string&path) const
|
|||
return;
|
||||
}
|
||||
|
||||
NetTaskDef*def = new NetTaskDef(path, st);
|
||||
/* Translate the wires that are ports to NetNet pointers by
|
||||
presuming that the name is already elaborated, and look it
|
||||
up in the design. Then save that pointer for later use by
|
||||
calls to the task. (Remember, the task itself does not need
|
||||
these ports.) */
|
||||
svector<NetNet*>ports (ports_->count());
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
NetNet*tmp = des->find_signal(path, (*ports_)[idx]->name());
|
||||
|
||||
ports[idx] = tmp;
|
||||
}
|
||||
|
||||
NetTaskDef*def = new NetTaskDef(path, st, ports);
|
||||
des->add_task(path, def);
|
||||
}
|
||||
|
||||
|
|
@ -1862,6 +1950,9 @@ Design* elaborate(const map<string,Module*>&modules,
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.59 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.58 1999/07/18 21:17:50 steve
|
||||
* Add support for CE input to XNF DFF, and do
|
||||
* complete cleanup of replaced design nodes.
|
||||
|
|
|
|||
21
netlist.cc
21
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: netlist.cc,v 1.47 1999/07/18 21:17:50 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.48 1999/07/24 02:11:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
|
|
@ -535,15 +535,13 @@ const NetExpr* NetSTask::parm(unsigned idx) const
|
|||
return parms_[idx];
|
||||
}
|
||||
|
||||
NetUTask::NetUTask(NetTaskDef*def, const svector<NetExpr*>&p)
|
||||
: task_(def), parms_(p)
|
||||
NetUTask::NetUTask(NetTaskDef*def)
|
||||
: task_(def)
|
||||
{
|
||||
}
|
||||
|
||||
NetUTask::~NetUTask()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||
delete parms_[idx];
|
||||
}
|
||||
|
||||
NetExpr::~NetExpr()
|
||||
|
|
@ -968,8 +966,8 @@ const NetExpr* NetRepeat::expr() const
|
|||
return expr_;
|
||||
}
|
||||
|
||||
NetTaskDef::NetTaskDef(const string&n, NetProc*p)
|
||||
: name_(n), proc_(p)
|
||||
NetTaskDef::NetTaskDef(const string&n, NetProc*p, const svector<NetNet*>&po)
|
||||
: name_(n), proc_(p), ports_(po)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -978,6 +976,12 @@ NetTaskDef::~NetTaskDef()
|
|||
delete proc_;
|
||||
}
|
||||
|
||||
NetNet* NetTaskDef::port(unsigned idx)
|
||||
{
|
||||
assert(idx < ports_.count());
|
||||
return ports_[idx];
|
||||
}
|
||||
|
||||
NetUDP::NetUDP(const string&n, unsigned pins, bool sequ)
|
||||
: NetNode(n, pins), sequential_(sequ), init_('x')
|
||||
{
|
||||
|
|
@ -1479,6 +1483,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.48 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.47 1999/07/18 21:17:50 steve
|
||||
* Add support for CE input to XNF DFF, and do
|
||||
* complete cleanup of replaced design nodes.
|
||||
|
|
|
|||
24
netlist.h
24
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: netlist.h,v 1.50 1999/07/18 21:17:50 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.51 1999/07/24 02:11:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -217,8 +217,8 @@ class NetNode : public NetObj {
|
|||
class NetNet : public NetObj, public LineInfo {
|
||||
|
||||
public:
|
||||
enum Type { IMPLICIT, WIRE, TRI, TRI1, SUPPLY0, WAND, TRIAND,
|
||||
TRI0, SUPPLY1, WOR, TRIOR, REG, INTEGER };
|
||||
enum Type { IMPLICIT, IMPLICIT_REG, WIRE, TRI, TRI1, SUPPLY0,
|
||||
WAND, TRIAND, TRI0, SUPPLY1, WOR, TRIOR, REG, INTEGER };
|
||||
|
||||
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
|
||||
|
||||
|
|
@ -885,17 +885,21 @@ class NetSTask : public NetProc {
|
|||
class NetTaskDef {
|
||||
|
||||
public:
|
||||
NetTaskDef(const string&n, NetProc*p);
|
||||
NetTaskDef(const string&n, NetProc*p, const svector<NetNet*>&po);
|
||||
~NetTaskDef();
|
||||
|
||||
const string& name() const { return name_; }
|
||||
const NetProc*proc() const { return proc_; }
|
||||
|
||||
unsigned port_count() const { return ports_.count(); }
|
||||
NetNet*port(unsigned idx);
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
string name_;
|
||||
NetProc*proc_;
|
||||
svector<NetNet*>ports_;
|
||||
|
||||
private: // not implemented
|
||||
NetTaskDef(const NetTaskDef&);
|
||||
|
|
@ -903,26 +907,21 @@ class NetTaskDef {
|
|||
};
|
||||
|
||||
/*
|
||||
* A call to a user defined task is elaborated into this object. I
|
||||
* save the parameters and the pointer to the task definition.
|
||||
* A call to a user defined task is elaborated into this object.
|
||||
*/
|
||||
class NetUTask : public NetProc {
|
||||
|
||||
public:
|
||||
NetUTask(NetTaskDef*, const svector<NetExpr*>&);
|
||||
NetUTask(NetTaskDef*);
|
||||
~NetUTask();
|
||||
|
||||
const string& name() const { return task_->name(); }
|
||||
unsigned nparms() const { return parms_.count(); }
|
||||
|
||||
const NetExpr* parm(unsigned idx) const;
|
||||
|
||||
virtual void emit_proc(ostream&, struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetTaskDef*task_;
|
||||
svector<NetExpr*>parms_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1376,6 +1375,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.51 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.50 1999/07/18 21:17:50 steve
|
||||
* Add support for CE input to XNF DFF, and do
|
||||
* complete cleanup of replaced design nodes.
|
||||
|
|
|
|||
37
netlist.txt
37
netlist.txt
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: netlist.txt,v 1.2 1999/07/21 01:15:29 steve Exp $"
|
||||
#ident "$Id: netlist.txt,v 1.3 1999/07/24 02:11:20 steve Exp $"
|
||||
|
||||
|
||||
Note that the netlist.h header contains detailed descriptions of how
|
||||
|
|
@ -155,10 +155,43 @@ connect to and receive signals from the structural aspects of the
|
|||
design.
|
||||
|
||||
The pins of a NetESignal object are passive. The values at the pin are
|
||||
only sampled with the process evaluates the expression that includes
|
||||
only sampled when the process evaluates the expression that includes
|
||||
the NetESignal object.
|
||||
|
||||
HIERARCHY IN NETLISTS
|
||||
|
||||
The obvious hierarchical structure of verilog is the module. The
|
||||
Verilog program may contain any number of instantiations of modules in
|
||||
order to form an hierarchical design. However, the elaboration of the
|
||||
design into a netlist erases module boundaries. Modules are expanded
|
||||
each place they are used, with the hierarchical instance name used to
|
||||
name the components of the module instance. However, the fact that a
|
||||
wire or register is a module port is lost.
|
||||
|
||||
The advantage of this behavior is first the simplification of the
|
||||
netlist structure itself. Backends that process netlists only need to
|
||||
cope with a list of nets, a list of nodes and a list of
|
||||
processes. This eases the task of the backend code generators.
|
||||
|
||||
Another advantage of this flattening of the netlist is that optimizers
|
||||
can operate globally, with optimizations freely crossing module
|
||||
boundaries. This makes coding of netlist transform functions such as
|
||||
constant propagation more effective and easier to write.
|
||||
|
||||
TASKS IN NETLISTS
|
||||
|
||||
The flattening of the design does not include tasks and named
|
||||
begin-end blocks. Tasks are behavioral hierarchy (whereas modules are
|
||||
structural) so do not easily succumb to the flattening process. In
|
||||
particular, it is logically impossible to flatten tasks that
|
||||
recurse. (The elaboration process does reserve the right to flatten
|
||||
some task calls. C++ programmers recognize this as inlining a task.)
|
||||
|
||||
|
||||
$Log: netlist.txt,v $
|
||||
Revision 1.3 1999/07/24 02:11:20 steve
|
||||
Elaborate task input ports.
|
||||
|
||||
Revision 1.2 1999/07/21 01:15:29 steve
|
||||
Document netlist semantics.
|
||||
|
||||
|
|
|
|||
32
parse.y
32
parse.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: parse.y,v 1.51 1999/07/12 00:59:36 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.52 1999/07/24 02:11:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -107,6 +107,7 @@ extern void lex_end_table();
|
|||
|
||||
%type <wire> port
|
||||
%type <wires> list_of_ports list_of_ports_opt
|
||||
%type <wires> task_item task_item_list task_item_list_opt
|
||||
|
||||
%type <portname> port_name
|
||||
%type <portnames> port_name_list
|
||||
|
|
@ -1542,32 +1543,53 @@ statement_opt
|
|||
|
||||
task_body
|
||||
: task_item_list_opt statement_opt
|
||||
{ PTask*tmp = new PTask($2);
|
||||
{ PTask*tmp = new PTask($1, $2);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
task_item
|
||||
: block_item_decl
|
||||
{ $$ = 0; }
|
||||
| K_input range_opt list_of_variables ';'
|
||||
{ yyerror(@1, "Sorry, task input ports not implemented.");
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, $2, $3);
|
||||
delete $2;
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output range_opt list_of_variables ';'
|
||||
{ yyerror(@1, "Sorry, task output ports not implemented.");
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT, $2, $3);
|
||||
delete $2;
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout range_opt list_of_variables ';'
|
||||
{ yyerror(@1, "Sorry, task inout ports not implemented.");
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT, $2, $3);
|
||||
delete $2;
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
task_item_list
|
||||
: task_item_list task_item
|
||||
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, *$2);
|
||||
delete $1;
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| task_item
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
task_item_list_opt
|
||||
: task_item_list
|
||||
{ $$ = $1; }
|
||||
|
|
||||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
udp_body
|
||||
|
|
|
|||
74
pform.cc
74
pform.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: pform.cc,v 1.32 1999/07/10 01:03:18 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.33 1999/07/24 02:11:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compiler.h"
|
||||
|
|
@ -426,6 +426,63 @@ void pform_set_port_type(const string&name, NetNet::PortType pt)
|
|||
VLerror("error setting port direction.");
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called by the parser to create task ports. The
|
||||
* resulting wire (which should be a register) is put into a list to
|
||||
* be packed into the task parameter list.
|
||||
*
|
||||
* It is possible that the wire (er, register) was already created,
|
||||
* but we know that if the name matches it is a part of the current
|
||||
* task, so in that case I just assign direction to it.
|
||||
*
|
||||
* The following example demonstrates some if the issues:
|
||||
*
|
||||
* task foo;
|
||||
* input a;
|
||||
* reg a, b;
|
||||
* input b;
|
||||
* [...]
|
||||
* endtask
|
||||
*
|
||||
* This function is called when the parser matches the "input a" and
|
||||
* the "input b" statements. For ``a'', this function is called before
|
||||
* the wire is declared as a register, so I create the foo.a
|
||||
* wire. For ``b'', I will find that there is already a foo.b and I
|
||||
* just set the port direction. In either case, the ``reg a, b''
|
||||
* statement is caught by the block_item non-terminal and processed there.
|
||||
*/
|
||||
svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
const svector<PExpr*>*range,
|
||||
const list<string>*names)
|
||||
{
|
||||
svector<PWire*>*res = new svector<PWire*>(0);
|
||||
for (list<string>::const_iterator cur = names->begin()
|
||||
; cur != names->end() ; cur ++ ) {
|
||||
|
||||
string name = scoped_name(*cur);
|
||||
|
||||
/* Look for a preexisting wire. If it exists, set the
|
||||
port direction. If not, create it. */
|
||||
PWire*curw = pform_cur_module->get_wire(name);
|
||||
if (curw) {
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt);
|
||||
pform_cur_module->add_wire(curw);
|
||||
}
|
||||
|
||||
/* If there is a range involved, it needs to be set. */
|
||||
if (range)
|
||||
curw->set_range((*range)[0], (*range)[1]);
|
||||
|
||||
svector<PWire*>*tmp = new svector<PWire*>(*res, curw);
|
||||
delete res;
|
||||
res = tmp;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void pform_set_task(const string&name, PTask*task)
|
||||
{
|
||||
pform_cur_module->add_task(name, task);
|
||||
|
|
@ -554,18 +611,6 @@ PProcess* pform_make_behavior(PProcess::Type type, Statement*st)
|
|||
return pp;
|
||||
}
|
||||
|
||||
#if 0
|
||||
Statement* pform_make_calltask(string*name, svector<PExpr*>*parms)
|
||||
{
|
||||
if (parms == 0)
|
||||
parms = new svector<PExpr*>(0);
|
||||
|
||||
PCallTask*ct = new PCallTask(*name, *parms);
|
||||
delete name;
|
||||
delete parms;
|
||||
return ct;
|
||||
}
|
||||
#endif
|
||||
|
||||
FILE*vl_input = 0;
|
||||
int pform_parse(const char*path, map<string,Module*>&modules,
|
||||
|
|
@ -593,6 +638,9 @@ int pform_parse(const char*path, map<string,Module*>&modules,
|
|||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.33 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.32 1999/07/10 01:03:18 steve
|
||||
* remove string from lexical phase.
|
||||
*
|
||||
|
|
|
|||
13
pform.h
13
pform.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: pform.h,v 1.23 1999/07/10 01:03:18 steve Exp $"
|
||||
#ident "$Id: pform.h,v 1.24 1999/07/24 02:11:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -145,6 +145,14 @@ extern void pform_make_modgates(const string&type, svector<lgate>*gates);
|
|||
/* Make a continuous assignment node, with optional bit- or part- select. */
|
||||
extern PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval);
|
||||
|
||||
|
||||
/* Given a port type and a list of names, make a list of wires that
|
||||
can be used as task port information. */
|
||||
extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
const svector<PExpr*>*range,
|
||||
const list<string>*names);
|
||||
|
||||
|
||||
/*
|
||||
* These are functions that the outside-the-parser code uses the do
|
||||
* interesting things to the verilog. The parse function reads and
|
||||
|
|
@ -157,6 +165,9 @@ extern void pform_dump(ostream&out, Module*mod);
|
|||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.24 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.23 1999/07/10 01:03:18 steve
|
||||
* remove string from lexical phase.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: pform_dump.cc,v 1.28 1999/07/17 19:51:00 steve Exp $"
|
||||
#ident "$Id: pform_dump.cc,v 1.29 1999/07/24 02:11:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -409,6 +409,22 @@ void PRepeat::dump(ostream&out, unsigned ind) const
|
|||
|
||||
void PTask::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
||||
out << setw(ind) << "";
|
||||
switch ((*ports_)[idx]->get_port_type()) {
|
||||
case NetNet::PINPUT:
|
||||
out << "input ";
|
||||
break;
|
||||
case NetNet::POUTPUT:
|
||||
out << "output ";
|
||||
break;
|
||||
case NetNet::PINOUT:
|
||||
out << "inout ";
|
||||
break;
|
||||
}
|
||||
out << (*ports_)[idx]->name() << ";" << endl;
|
||||
}
|
||||
|
||||
statement_->dump(out, ind);
|
||||
}
|
||||
|
||||
|
|
@ -530,6 +546,9 @@ void PUdp::dump(ostream&out) const
|
|||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.29 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.28 1999/07/17 19:51:00 steve
|
||||
* netlist support for ternary operator.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue