Catch memory word parameters to tasks.

This commit is contained in:
steve 2000-04-28 16:50:53 +00:00
parent 1f7090135b
commit 08e9a114a2
5 changed files with 192 additions and 32 deletions

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.47 2000/04/26 20:53:21 steve Exp $"
#ident "$Id: Makefile.in,v 1.48 2000/04/28 16:50:53 steve Exp $"
#
#
SHELL = /bin/sh
@ -77,7 +77,7 @@ net_design.o net_event.o net_scope.o net_udp.o nexus_from_link.o \
pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.o \
verinum.o verireal.o target.o targets.o Module.o PDelays.o PEvent.o \
verinum.o verireal.o target.o targets.o util.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o \
PTask.o PFunction.o PWire.o Statement.o \
$(FF) $(TT)

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: elaborate.cc,v 1.162 2000/04/23 03:45:24 steve Exp $"
#ident "$Id: elaborate.cc,v 1.163 2000/04/28 16:50:53 steve Exp $"
#endif
/*
@ -33,7 +33,7 @@
# include "PEvent.h"
# include "netlist.h"
# include "netmisc.h"
# include "util.h"
// Urff, I don't like this global variable. I *will* figure out a
// way to get rid of it. But, for now the PGModule::elaborate method
@ -41,6 +41,7 @@
static const map<string,Module*>* modlist = 0;
static const map<string,PUdp*>* udplist = 0;
/*
* Elaborate a source wire. The "wire" is the declaration of wires,
* registers, ports and memories. The parser has already merged the
@ -50,6 +51,21 @@ static const map<string,PUdp*>* udplist = 0;
*/
void PWire::elaborate(Design*des, NetScope*scope) const
{
/* The parser may produce hierarchical names for wires. I here
follow the scopes down to the base where I actually want to
elaborate the NetNet object. */
string basename = name_;
for (;;) {
string p = parse_first_name(basename);
if (basename == "") {
basename = p;
break;
}
scope = scope->child(p);
assert(scope);
}
const string path = scope->name();
NetNet::Type wtype = type_;
if (wtype == NetNet::IMPLICIT)
@ -100,7 +116,7 @@ void PWire::elaborate(Design*des, NetScope*scope) const
cerr << get_line() << ": error: Inconsistent width, "
"[" << mnum[idx] << ":" << lnum[idx] << "]"
" vs. [" << mnum[0] << ":" << lnum[0] << "]"
" for signal ``" << name_ << "''" << endl;
" for signal ``" << basename << "''" << endl;
des->errors += 1;
return;
}
@ -130,13 +146,13 @@ void PWire::elaborate(Design*des, NetScope*scope) const
long rnum = rval->as_long();
delete lval;
delete rval;
NetMemory*sig = new NetMemory(path+"."+name_, wid, lnum, rnum);
NetMemory*sig = new NetMemory(path+"."+basename, wid, lnum, rnum);
sig->set_attributes(attributes);
des->add_memory(sig);
} else {
NetNet*sig = new NetNet(scope, path + "." + name_, wtype, msb, lsb);
NetNet*sig = new NetNet(scope, path + "." +basename, wtype, msb, lsb);
sig->set_line(*this);
sig->port_type(port_type_);
sig->set_attributes(attributes);
@ -745,6 +761,12 @@ NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix,
assert(rv);
rv->set_width(mem->width());
if (ix == 0) {
cerr << get_line() << ": internal error: No index in lval "
<< "of assignment to memory?" << endl;
return 0;
}
assert(ix);
NetNet*idx = ix->elaborate_net(des, path, 0, 0, 0, 0);
assert(idx);
@ -884,6 +906,10 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
const PEIdent*id = dynamic_cast<const PEIdent*>(lval());
if (id == 0) break;
NetNet*net = des->find_signal(path, id->name());
if (net && (net->scope() == scope))
break;
if (NetMemory*mem = des->find_memory(path, id->name()))
return assign_to_memory_(mem, id->msb_, des, path);
@ -927,7 +953,7 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
delete rv;
rv = tmp;
}
NetAssign*cur;
/* Rewrite delayed assignments as assignments that are
@ -1434,10 +1460,13 @@ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const
NetBlock*block = new NetBlock(NetBlock::SEQU);
/* Generate assignment statement statements for the input and
INOUT ports of the task. These are managed by writing
assignments with the task port the l-value and the passed
expression the r-value. */
expression the r-value. We know by definition that the port
is a reg type, so this elaboration is pretty obvious. */
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
NetNet*port = def->port(idx);
@ -1457,27 +1486,67 @@ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const
cur = new NetUTask(def);
block->append(cur);
/* Generate assignment statement statements for the output and
INOUT ports of the task. The l-value in this case is the
/* Generate assignment statements for the output and INOUT
ports of the task. The l-value in this case is the
expression passed as a parameter, and the r-value is the
port to be copied out. */
port to be copied out.
We know by definition that the r-value of this copy-out is
the port, which is a reg. The l-value, however, may be any
expression that can be a target to a procedural
assignment, including a memory word. */
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
NetNet*port = def->port(idx);
/* Skip input ports. */
assert(port->port_type() != NetNet::NOT_A_PORT);
if (port->port_type() == NetNet::PINPUT)
continue;
const PEIdent*id;
NetNet*val = 0;
NetMemory*mem = 0;
if ( (id = dynamic_cast<const PEIdent*>(parms_[idx])) )
des->find_symbol(scope, id->name(), val, mem);
/* Catch the case of memory words passed as an out
parameter. Generate an assignment to memory instead
of a normal assignment. */
if (mem != 0) {
assert(id->msb_);
NetNet*ix = id->msb_->elaborate_net(des, path,
0, 0, 0, 0);
assert(ix);
NetExpr*rv = new NetESignal(port);
if (rv->expr_width() < mem->width())
rv = pad_to_width(rv, mem->width());
NetAssignMem*am = new NetAssignMem(mem, ix, rv);
am->set_line(*this);
block->append(am);
continue;
}
/* Elaborate the parameter expression as a net so that
it can be used as an l-value. Then check that the
parameter width match up. */
NetNet*val = parms_[idx]->elaborate_net(des, path,
0, 0, 0, 0);
parameter width match up.
XXXX FIXME XXXX This goes nuts if the parameter is a
memory word. that must be handled by generating
NetAssignMem objects instead. */
if (val == 0)
val = parms_[idx]->elaborate_net(des, path,
0, 0, 0, 0);
assert(val);
/* Make an expression out of the actual task port. If
the port is smaller then the expression to redeive
the port is smaller then the expression to receive
the result, then expand the port by padding with
zeros. */
NetESignal*sig = new NetESignal(port);
@ -2031,6 +2100,9 @@ NetProc* PRepeat::elaborate(Design*des, const string&path) const
*/
void PTask::elaborate_1(Design*des, const string&path) const
{
NetScope*scope = des->find_scope(path);
assert(scope);
/* 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
@ -2040,6 +2112,7 @@ void PTask::elaborate_1(Design*des, const string&path) const
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
NetNet*tmp = des->find_signal(path, (*ports_)[idx]->name());
assert(tmp->scope() == scope);
ports[idx] = tmp;
}
@ -2268,6 +2341,9 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.163 2000/04/28 16:50:53 steve
* Catch memory word parameters to tasks.
*
* Revision 1.162 2000/04/23 03:45:24 steve
* Add support for the procedural release statement.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: net_design.cc,v 1.4 2000/04/10 05:26:06 steve Exp $"
#ident "$Id: net_design.cc,v 1.5 2000/04/28 16:50:53 steve Exp $"
#endif
/*
@ -26,22 +26,9 @@
*/
# include "netlist.h"
# include "util.h"
# include <strstream>
static string parse_first_name(string&path)
{
unsigned pos = path.find('.');
if (pos > path.length()) {
string res = path;
path = "";
return res;
}
string res = path.substr(0, pos);
path = path.substr(pos+1, path.length());
return res;
}
static string parse_last_name(string&path)
{
unsigned pos = path.rfind('.');
@ -365,6 +352,47 @@ NetMemory* Design::find_memory(const string&path, const string&name)
return 0;
}
void Design::find_symbol(const NetScope*scope, const string&key,
NetNet*&sig, NetMemory*&mem)
{
sig = 0;
mem = 0;
for (;;) {
/* Form the full heirarchical name for lookups. */
string fulname = scope? (scope->name() + "." + key) : key;
/* Is this a signal? If so, we are done. */
if (signals_) {
NetNet*cur = signals_;
do {
if (cur->name() == fulname) {
sig = cur;
return;
}
cur = cur->sig_prev_;
} while (cur != signals_);
}
/* Is this a memory? If so, we are again done. */
map<string,NetMemory*>::const_iterator cur
= memories_.find(fulname);
if (cur != memories_.end()) {
mem = (*cur).second;
return;
}
/* Neither a signal nor memory are found, so go up a
scope level and try again. */
if (scope == 0)
return;
scope = scope->parent();
}
}
void Design::add_function(const string&key, NetFuncDef*def)
{
funcs_[key] = def;
@ -548,6 +576,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $Log: net_design.cc,v $
* Revision 1.5 2000/04/28 16:50:53 steve
* Catch memory word parameters to tasks.
*
* Revision 1.4 2000/04/10 05:26:06 steve
* All events now use the NetEvent class.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.h,v 1.130 2000/04/23 21:17:31 steve Exp $"
#ident "$Id: netlist.h,v 1.131 2000/04/28 16:50:53 steve Exp $"
#endif
/*
@ -2333,6 +2333,11 @@ class Design {
void add_memory(NetMemory*);
NetMemory* find_memory(const string&path, const string&name);
/* This is a more general lookup that finds the named signal
or memory, whichever is first in the search path. */
void find_symbol(const NetScope*,const string&key,
NetNet*&sig, NetMemory*&mem);
// Functions
void add_function(const string&n, NetFuncDef*);
NetFuncDef* find_function(const string&path, const string&key);
@ -2446,6 +2451,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.131 2000/04/28 16:50:53 steve
* Catch memory word parameters to tasks.
*
* Revision 1.130 2000/04/23 21:17:31 steve
* Better comments about bufif devices.
*

45
util.cc Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2000 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.
*
* 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
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: util.cc,v 1.1 2000/04/28 16:50:53 steve Exp $"
#endif
# include "util.h"
string parse_first_name(string&path)
{
unsigned pos = path.find('.');
if (pos > path.length()) {
string res = path;
path = "";
return res;
}
string res = path.substr(0, pos);
path = path.substr(pos+1, path.length());
return res;
}
/*
* $Log: util.cc,v $
* Revision 1.1 2000/04/28 16:50:53 steve
* Catch memory word parameters to tasks.
*
*/