Elaborate class task and function methods.
The parse of class methods already works, this patch forms the methods into their own scopes, and elaborates those scopes. The "this"
This commit is contained in:
parent
fac5cbca43
commit
17330a3073
6
PExpr.h
6
PExpr.h
|
|
@ -372,6 +372,7 @@ class PEIdent : public PExpr {
|
|||
std::list<long>&prefix_indices) const;
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_method_class_member_(Design*, NetScope*) const;
|
||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
|
||||
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
|
||||
|
|
@ -449,6 +450,11 @@ class PEIdent : public PExpr {
|
|||
NetScope*found,
|
||||
bool need_const) const;
|
||||
|
||||
NetExpr*elaborate_expr_class_member_(Design*des,
|
||||
NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
# include <cassert>
|
||||
|
||||
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
|
||||
: PTaskFunc(name, parent), ports_(0), statement_(0)
|
||||
: PTaskFunc(name, parent), statement_(0)
|
||||
{
|
||||
is_auto_ = is_auto__;
|
||||
return_type_.type = PTF_NONE;
|
||||
|
|
@ -32,12 +32,6 @@ PFunction::~PFunction()
|
|||
{
|
||||
}
|
||||
|
||||
void PFunction::set_ports(vector<PWire *>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
ports_ = p;
|
||||
}
|
||||
|
||||
void PFunction::set_statement(Statement*s)
|
||||
{
|
||||
assert(s != 0);
|
||||
|
|
|
|||
29
PTask.cc
29
PTask.cc
|
|
@ -22,7 +22,7 @@
|
|||
# include <cassert>
|
||||
|
||||
PTaskFunc::PTaskFunc(perm_string n, LexicalScope*p)
|
||||
: PScope(n,p), this_type_(0)
|
||||
: PScope(n,p), this_type_(0), ports_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -30,14 +30,31 @@ PTaskFunc::~PTaskFunc()
|
|||
{
|
||||
}
|
||||
|
||||
void PTaskFunc::set_this(class_type_t*type)
|
||||
void PTaskFunc::set_ports(vector<PWire*>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
ports_ = p;
|
||||
}
|
||||
|
||||
void PTaskFunc::set_this(class_type_t*type, PWire*this_wire)
|
||||
{
|
||||
assert(this_type_ == 0);
|
||||
this_type_ = type;
|
||||
|
||||
// Push a synthetis argument that is the "this" value.
|
||||
if (ports_==0)
|
||||
ports_ = new vector<PWire*>;
|
||||
|
||||
size_t use_size = ports_->size();
|
||||
ports_->resize(use_size + 1);
|
||||
for (size_t idx = use_size ; idx > 0 ; idx -= 1)
|
||||
ports_->at(idx) = ports_->at(idx-1);
|
||||
|
||||
ports_->at(0) = this_wire;
|
||||
}
|
||||
|
||||
PTask::PTask(perm_string name, LexicalScope*parent, bool is_auto__)
|
||||
: PTaskFunc(name, parent), ports_(0), statement_(0)
|
||||
: PTaskFunc(name, parent), statement_(0)
|
||||
{
|
||||
is_auto_ = is_auto__;
|
||||
}
|
||||
|
|
@ -46,12 +63,6 @@ PTask::~PTask()
|
|||
{
|
||||
}
|
||||
|
||||
void PTask::set_ports(vector<PWire*>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
ports_ = p;
|
||||
}
|
||||
|
||||
void PTask::set_statement(Statement*s)
|
||||
{
|
||||
assert(statement_ == 0);
|
||||
|
|
|
|||
16
PTask.h
16
PTask.h
|
|
@ -26,6 +26,7 @@
|
|||
# include <vector>
|
||||
# include <list>
|
||||
class Design;
|
||||
class NetNet;
|
||||
class NetScope;
|
||||
class PWire;
|
||||
class Statement;
|
||||
|
|
@ -56,14 +57,23 @@ class PTaskFunc : public PScope, public LineInfo {
|
|||
PTaskFunc(perm_string name, LexicalScope*parent);
|
||||
~PTaskFunc();
|
||||
|
||||
void set_this(class_type_t*use_type);
|
||||
void set_ports(std::vector<PWire *>*p);
|
||||
|
||||
void set_this(class_type_t*use_type, PWire*this_wire);
|
||||
|
||||
// If this task is a method of a class, this returns a pointer
|
||||
// to the class type.
|
||||
inline class_type_t* method_of() const { return this_type_; }
|
||||
|
||||
protected:
|
||||
void elaborate_sig_ports_(Design*des, NetScope*scope,
|
||||
std::vector<NetNet*>&ports) const;
|
||||
|
||||
void dump_ports_(std::ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
class_type_t*this_type_;
|
||||
std::vector<PWire*>*ports_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -75,7 +85,6 @@ class PTask : public PTaskFunc {
|
|||
explicit PTask(perm_string name, LexicalScope*parent, bool is_auto);
|
||||
~PTask();
|
||||
|
||||
void set_ports(std::vector<PWire *>*p);
|
||||
void set_statement(Statement *s);
|
||||
|
||||
// Tasks introduce scope, to need to be handled during the
|
||||
|
|
@ -95,7 +104,6 @@ class PTask : public PTaskFunc {
|
|||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
std::vector<PWire*>*ports_;
|
||||
Statement*statement_;
|
||||
bool is_auto_;
|
||||
|
||||
|
|
@ -117,7 +125,6 @@ class PFunction : public PTaskFunc {
|
|||
explicit PFunction(perm_string name, LexicalScope*parent, bool is_auto);
|
||||
~PFunction();
|
||||
|
||||
void set_ports(std::vector<PWire *>*p);
|
||||
void set_statement(Statement *s);
|
||||
void set_return(PTaskFuncArg t);
|
||||
|
||||
|
|
@ -135,7 +142,6 @@ class PFunction : public PTaskFunc {
|
|||
|
||||
private:
|
||||
PTaskFuncArg return_type_;
|
||||
std::vector<PWire *> *ports_;
|
||||
Statement *statement_;
|
||||
bool is_auto_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include "discipline.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netvector.h"
|
||||
# include "ivl_assert.h"
|
||||
|
|
@ -747,7 +748,7 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "task " << scope_path(scope_) << ";" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < ports_.size() ; idx += 1) {
|
||||
o << setw(ind+4) << "";
|
||||
assert(ports_[idx]);
|
||||
switch (ports_[idx]->port_type()) {
|
||||
|
|
@ -767,7 +768,10 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
|
|||
o << ports_[idx]->name() << ";" << endl;
|
||||
}
|
||||
|
||||
proc_->dump(o, ind+4);
|
||||
if (proc_)
|
||||
proc_->dump(o, ind+4);
|
||||
else
|
||||
o << setw(ind+4) << "" << "MISSING PROCEDURAL CODE" << endl;
|
||||
|
||||
o << setw(ind) << "" << "endtask" << endl;
|
||||
}
|
||||
|
|
@ -1140,7 +1144,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
|
|||
if (statement_)
|
||||
statement_->dump(o, ind+2);
|
||||
else
|
||||
o << setw(ind+2) << "" << "// NO STATEMENT" << endl;
|
||||
o << setw(ind+2) << "" << "MISSING PROCEDURAL CODE" << endl;
|
||||
}
|
||||
|
||||
void NetPDelay::dump(ostream&o, unsigned ind) const
|
||||
|
|
@ -1173,6 +1177,11 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
|
|||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void netclass_t::dump_scope(ostream&fd) const
|
||||
{
|
||||
class_scope_->dump(fd);
|
||||
}
|
||||
|
||||
void NetScope::dump(ostream&o) const
|
||||
{
|
||||
/* This is a constructed hierarchical name. */
|
||||
|
|
@ -1320,6 +1329,11 @@ void NetScope::dump(ostream&o) const
|
|||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
; cur != children_.end() ; ++ cur )
|
||||
cur->second->dump(o);
|
||||
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++ cur ) {
|
||||
cur->second->dump_scope(o);
|
||||
}
|
||||
}
|
||||
|
||||
void NetSTask::dump(ostream&o, unsigned ind) const
|
||||
|
|
@ -1588,7 +1602,7 @@ void NetETernary::dump(ostream&o) const
|
|||
|
||||
void NetEUFunc::dump(ostream&o) const
|
||||
{
|
||||
o << func_->basename() << "(";
|
||||
o << scope_path(func_) << "(";
|
||||
if (! parms_.empty()) {
|
||||
parms_[0]->dump(o);
|
||||
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
|
||||
|
|
|
|||
99
elab_expr.cc
99
elab_expr.cc
|
|
@ -1163,6 +1163,30 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
if (netclass_t*class_type = net->class_type()) {
|
||||
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
|
||||
<< "Try to find method " << method_name
|
||||
<< " of class " << class_type->get_name() << endl;
|
||||
|
||||
NetScope*func = class_type->method_from_name(method_name);
|
||||
if (func == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the function result size be getting the details
|
||||
// from the variable in the function scope that has the
|
||||
// name of the function.
|
||||
if (NetNet*res = func->find_signal(method_name)) {
|
||||
expr_type_ = res->data_type();
|
||||
expr_width_= res->vector_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = res->get_signed();
|
||||
return expr_width_;
|
||||
} else {
|
||||
ivl_assert(*this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1991,6 +2015,25 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
if (netclass_t*class_type = net->class_type()) {
|
||||
NetScope*func = class_type->method_from_name(method_name);
|
||||
if (func == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet*res = func->find_signal(func->basename());
|
||||
ivl_assert(*this, res);
|
||||
|
||||
vector<NetExpr*>parms;
|
||||
cerr << get_fileline() << ": PECallFunction::elaborate_expr_method_: "
|
||||
<< "Stub arguments to the function method." << endl;
|
||||
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
NetEUFunc*call = new NetEUFunc(scope, func, eres, parms, false);
|
||||
call->set_line(*this);
|
||||
return call;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2699,6 +2742,51 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Guess that the path_ is the name of a member of a containing class,
|
||||
* and see how that works. If it turns out that the current scope is
|
||||
* not a method, or the name is not in the parent class, then
|
||||
* fail. Otherwise, return a NetEProperty.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_class_member_(Design*, NetScope*scope,
|
||||
unsigned, unsigned) const
|
||||
{
|
||||
if (!gn_system_verilog())
|
||||
return 0;
|
||||
if (scope->parent() == 0)
|
||||
return 0;
|
||||
if (path_.size() != 1)
|
||||
return 0;
|
||||
|
||||
const netclass_t*class_type = scope->parent()->class_def();
|
||||
if (class_type == 0)
|
||||
return 0;
|
||||
|
||||
perm_string member_name = peek_tail_name(path_);
|
||||
int pidx = class_type->property_idx_from_name(member_name);
|
||||
if (pidx < 0)
|
||||
return 0;
|
||||
|
||||
NetNet*this_net = scope->find_signal(perm_string::literal("@"));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope)
|
||||
<< "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member: "
|
||||
<< "Found member " << member_name
|
||||
<< " is a member of class " << class_type->get_name()
|
||||
<< ", so synthesizing a NetEProperty." << endl;
|
||||
}
|
||||
|
||||
NetEProperty*tmp = new NetEProperty(this_net, member_name);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate an identifier in an expression. The identifier can be a
|
||||
* parameter name, a signal name or a memory name. It can also be a
|
||||
|
|
@ -2721,6 +2809,17 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
// Special case: Detect the special situation that this name
|
||||
// is the name of a variable in the class, and this is a class
|
||||
// method. We sense that this might be the case by noting that
|
||||
// the parent scope of where we are working is a
|
||||
// NetScope::CLASS, the path_ is a single component, and the
|
||||
// name is a property of the class. If that turns out to be
|
||||
// the case, then handle this specially.
|
||||
if (NetExpr*tmp = elaborate_expr_class_member_(des, scope, expr_wid, flags)) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (path_.size() > 1) {
|
||||
if (NEED_CONST & flags) {
|
||||
cerr << get_fileline() << ": error: A hierarchical reference"
|
||||
|
|
|
|||
38
elab_lval.cc
38
elab_lval.cc
|
|
@ -158,6 +158,11 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
NetEvent* eve = 0;
|
||||
perm_string method_name;
|
||||
|
||||
/* Try to detect the special case that we are in a method and
|
||||
the identifier is a member of the class. */
|
||||
if (NetAssign_*tmp = elaborate_lval_method_class_member_(des, scope))
|
||||
return tmp;
|
||||
|
||||
symbol_search(this, des, scope, path_, reg, par, eve);
|
||||
|
||||
/* If the signal is not found, check to see if this is a
|
||||
|
|
@ -296,6 +301,39 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||
NetScope*scope) const
|
||||
{
|
||||
if (!gn_system_verilog())
|
||||
return 0;
|
||||
if (scope->parent() == 0)
|
||||
return 0;
|
||||
if (path_.size() != 1)
|
||||
return 0;
|
||||
|
||||
const netclass_t*class_type = scope->parent()->class_def();
|
||||
if (class_type == 0)
|
||||
return 0;
|
||||
|
||||
perm_string member_name = peek_tail_name(path_);
|
||||
int pidx = class_type->property_idx_from_name(member_name);
|
||||
if (pidx < 0)
|
||||
return 0;
|
||||
|
||||
NetNet*this_net = scope->find_signal(perm_string::literal("@"));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope)
|
||||
<< "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*this_lval = new NetAssign_(this_net);
|
||||
this_lval->set_property(member_name);
|
||||
|
||||
return this_lval;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
|
|
|
|||
|
|
@ -296,6 +296,18 @@ static void elaborate_scope_class(Design*des, NetScope*scope,
|
|||
class_type_t*use_type = pclass->type;
|
||||
netclass_t*use_class = new netclass_t(use_type->name);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << pclass->get_fileline() <<": debug: "
|
||||
<< "Elaborate scope class " << pclass->pscope_name() << endl;
|
||||
}
|
||||
|
||||
// Class scopes have no parent scope, because references are
|
||||
// not allowed to escape a class method.
|
||||
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
|
||||
NetScope::CLASS);
|
||||
class_scope->set_class_def(use_class);
|
||||
use_class->set_class_scope(class_scope);
|
||||
|
||||
for (map<perm_string, data_type_t*>::iterator cur = use_type->properties.begin()
|
||||
; cur != use_type->properties.end() ; ++ cur) {
|
||||
ivl_type_s*tmp = cur->second->elaborate_type(des, scope);
|
||||
|
|
@ -304,14 +316,38 @@ static void elaborate_scope_class(Design*des, NetScope*scope,
|
|||
|
||||
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
||||
; cur != pclass->tasks.end() ; ++cur) {
|
||||
cerr << cur->second->get_fileline() << ": sorry: "
|
||||
<< "Class methods (tasks) not supported." << endl;
|
||||
|
||||
hname_t use_name (cur->first);
|
||||
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::TASK);
|
||||
// Task methods are always automatic...
|
||||
method_scope->is_auto(true);
|
||||
method_scope->set_line(cur->second);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate method (task) scope "
|
||||
<< scope_path(method_scope) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate_scope(des, method_scope);
|
||||
}
|
||||
|
||||
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
||||
; cur != pclass->funcs.end() ; ++cur) {
|
||||
cerr << cur->second->get_fileline() << ": sorry: "
|
||||
<< "Class methods (functions) not supported." << endl;
|
||||
|
||||
hname_t use_name (cur->first);
|
||||
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::FUNC);
|
||||
// Function methods are always automatic...
|
||||
method_scope->is_auto(true);
|
||||
method_scope->set_line(cur->second);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate method (function) scope "
|
||||
<< scope_path(method_scope) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate_scope(des, method_scope);
|
||||
}
|
||||
|
||||
scope->add_class(use_class);
|
||||
|
|
|
|||
209
elab_sig.cc
209
elab_sig.cc
|
|
@ -25,6 +25,7 @@
|
|||
# include <iostream>
|
||||
|
||||
# include "Module.h"
|
||||
# include "PClass.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PGenerate.h"
|
||||
|
|
@ -182,6 +183,15 @@ static void elaborate_sig_tasks(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
static void elaborate_sig_classes(Design*des, NetScope*scope,
|
||||
const map<perm_string,PClass*>&classes)
|
||||
{
|
||||
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
|
||||
; cur != classes.end() ; ++ cur) {
|
||||
netclass_t*use_class = scope->find_class(cur->second->pscope_name());
|
||||
use_class->elaborate_sig(des, cur->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
|
|
@ -262,6 +272,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
elaborate_sig_classes(des, scope, classes);
|
||||
|
||||
// initial and always blocks may contain begin-end and
|
||||
// fork-join blocks that can introduce scopes. Therefore, I
|
||||
|
|
@ -278,6 +289,34 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
|||
return flag;
|
||||
}
|
||||
|
||||
void netclass_t::elaborate_sig(Design*des, PClass*pclass)
|
||||
{
|
||||
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
||||
; cur != pclass->funcs.end() ; ++ cur) {
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": netclass_t::elaborate_sig: "
|
||||
<< "Elaborate signals in function method " << cur->first << endl;
|
||||
}
|
||||
|
||||
NetScope*scope = class_scope_->child( hname_t(cur->first) );
|
||||
ivl_assert(*cur->second, scope);
|
||||
cur->second->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
||||
; cur != pclass->tasks.end() ; ++ cur) {
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": netclass_t::elaborate_sig: "
|
||||
<< "Elaborate signals in task method " << cur->first << endl;
|
||||
}
|
||||
|
||||
NetScope*scope = class_scope_->child( hname_t(cur->first) );
|
||||
ivl_assert(*cur->second, scope);
|
||||
cur->second->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool PGate::elaborate_sig(Design*, NetScope*) const
|
||||
{
|
||||
return true;
|
||||
|
|
@ -475,17 +514,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
/* Make sure the function has at least one input port. If it
|
||||
fails this test, print an error message. Keep going so we
|
||||
can find more errors. */
|
||||
if (ports_ == 0 && !gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": error: Function " << fname
|
||||
<< " has no ports." << endl;
|
||||
cerr << get_fileline() << ": : Functions must have"
|
||||
<< " at least one input port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetNet*ret_sig = 0;
|
||||
netvector_t*ret_vec = 0;
|
||||
|
||||
|
|
@ -621,63 +649,15 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
break;
|
||||
|
||||
default:
|
||||
if (ports_) {
|
||||
cerr << get_fileline() << ": internal error: I don't know "
|
||||
<< "how to deal with return type of function "
|
||||
<< scope->basename() << "." << endl;
|
||||
} else {
|
||||
/* If we do not have any ports or a return type this
|
||||
* is probably a bad function definition. */
|
||||
cerr << get_fileline() << ": error: Bad definition for "
|
||||
<< "function " << scope->basename() << "?" << endl;
|
||||
return;
|
||||
}
|
||||
/* If we do not have any ports or a return type this
|
||||
* is probably a bad function definition. */
|
||||
cerr << get_fileline() << ": error: Bad definition for "
|
||||
<< "function " << scope->basename() << "?" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
vector<NetNet*>ports (ports_? ports_->size() : 0);
|
||||
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->size() ; idx += 1) {
|
||||
|
||||
/* Parse the port name into the task name and the reg
|
||||
name. We know by design that the port name is given
|
||||
as two components: <func>.<port>. */
|
||||
|
||||
perm_string pname = (*ports_)[idx]->basename();
|
||||
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
ports[idx] = 0;
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< scope_path(scope) << " is missing port "
|
||||
<< pname << "." << endl;
|
||||
scope->dump(cerr);
|
||||
cerr << get_fileline() << ": Continuing..." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< scope_path(scope) << " port " << pname
|
||||
<< " is a port but is not a port?" << endl;
|
||||
des->errors += 1;
|
||||
scope->dump(cerr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
if (tmp->port_type() != NetNet::PINPUT) {
|
||||
cerr << tmp->get_fileline() << ": error: function "
|
||||
<< scope_path(scope) << " port " << pname
|
||||
<< " is not an input port." << endl;
|
||||
cerr << tmp->get_fileline() << ": : Function arguments "
|
||||
<< "must be input ports." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
vector<NetNet*>ports;
|
||||
elaborate_sig_ports_(des, scope, ports);
|
||||
|
||||
NetFuncDef*def = 0;
|
||||
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
|
||||
|
|
@ -710,27 +690,8 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->size() : 0);
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
|
||||
perm_string port_name = (*ports_)[idx]->basename();
|
||||
|
||||
/* Find the signal for the port. We know by definition
|
||||
that it is in the scope of the task, so look only in
|
||||
the scope. */
|
||||
NetNet*tmp = scope->find_signal(port_name);
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Could not find port " << port_name
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
scope->dump(cerr);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
}
|
||||
|
||||
vector<NetNet*>ports;
|
||||
elaborate_sig_ports_(des, scope, ports);
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports);
|
||||
scope->set_task_def(def);
|
||||
|
||||
|
|
@ -739,6 +700,68 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
|||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
|
||||
vector<NetNet*>&ports) const
|
||||
{
|
||||
if (ports_ == 0) {
|
||||
ports.clear();
|
||||
|
||||
/* Make sure the function has at least one input
|
||||
port. If it fails this test, print an error
|
||||
message. Keep going so we can find more errors. */
|
||||
if (scope->type()==NetScope::FUNC && !gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Function " << scope->basename()
|
||||
<< " has no ports." << endl;
|
||||
cerr << get_fileline() << ": : "
|
||||
<< "Functions must have at least one input port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ports.resize(ports_->size());
|
||||
|
||||
for (size_t idx = 0 ; idx < ports_->size() ; idx += 1) {
|
||||
|
||||
perm_string port_name = ports_->at(idx)->basename();
|
||||
|
||||
ports[idx] = 0;
|
||||
NetNet*tmp = scope->find_signal(port_name);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "task/function " << scope_path(scope)
|
||||
<< " is missing port " << port_name << "." << endl;
|
||||
scope->dump(cerr);
|
||||
cerr << get_fileline() << ": Continuing..." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "task/function " << scope_path(scope)
|
||||
<< " port " << port_name
|
||||
<< " is a port but is not a port?" << endl;
|
||||
des->errors += 1;
|
||||
scope->dump(cerr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
if (scope->type()==NetScope::FUNC && tmp->port_type()!=NetNet::PINPUT) {
|
||||
cerr << tmp->get_fileline() << ": error: "
|
||||
<< "Function " << scope_path(scope)
|
||||
<< " port " << port_name
|
||||
<< " is not an inputport." << endl;
|
||||
cerr << tmp->get_fileline() << ": : "
|
||||
<< "Function arguments must be input ports." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PBlock::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetScope*my_scope = scope;
|
||||
|
|
@ -1210,6 +1233,18 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
// do right now is locate the netclass_t object for the
|
||||
// class, and use that to build the net.
|
||||
netclass_t*use_type = locate_class_type(des, scope, class_type);
|
||||
if (use_type == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Class " << class_type->name
|
||||
<< " isn't elaborated in scope=" << scope_path(scope) << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
ivl_assert(*this, use_type);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Create class instance signal " << wtype
|
||||
<< " " << name_ << endl;
|
||||
}
|
||||
// (No arrays of classes)
|
||||
list<netrange_t> use_unpacked;
|
||||
sig = new NetNet(scope, name_, wtype, use_unpacked, use_type);
|
||||
|
|
|
|||
64
elaborate.cc
64
elaborate.cc
|
|
@ -31,6 +31,7 @@
|
|||
# include <sstream>
|
||||
# include <list>
|
||||
# include "pform.h"
|
||||
# include "PClass.h"
|
||||
# include "PEvent.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PPackage.h"
|
||||
|
|
@ -3325,6 +3326,20 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
|
|||
return sys;
|
||||
}
|
||||
|
||||
if (netclass_t*class_type = net->class_type()) {
|
||||
NetScope*task = class_type->method_from_name(method_name);
|
||||
if (task == 0) {
|
||||
cerr << get_fileline() << ": XXXXX: "
|
||||
<< "Can't find task " << method_name
|
||||
<< " in class " << class_type->get_name() << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetUTask*tmp = new NetUTask(task);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4679,6 +4694,16 @@ static void elaborate_tasks(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
static void elaborate_classes(Design*des, NetScope*scope,
|
||||
const map<perm_string,PClass*>&classes)
|
||||
{
|
||||
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
|
||||
; cur != classes.end() ; ++ cur) {
|
||||
netclass_t*use_class = scope->find_class(cur->second->pscope_name());
|
||||
use_class->elaborate(des, cur->second);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When a module is instantiated, it creates the scope then uses this
|
||||
* method to elaborate the contents of the module.
|
||||
|
|
@ -4703,6 +4728,9 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
|||
// the signals so that the tasks can reference them.
|
||||
elaborate_tasks(des, scope, tasks);
|
||||
|
||||
// Elaboate class definitions.
|
||||
elaborate_classes(des, scope, classes);
|
||||
|
||||
// Get all the gates of the module and elaborate them by
|
||||
// connecting them to the signals. The gate may be simple or
|
||||
// complex.
|
||||
|
|
@ -4730,6 +4758,42 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
|||
return result_flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborating a netclass_t means elaborating the PFunction and PTask
|
||||
* objects that it contains. The scopes and signals have already been
|
||||
* elaborated in the class of the netclass_t scope, so we can get the
|
||||
* child scope for each definition and use that for the context of the
|
||||
* function.
|
||||
*/
|
||||
void netclass_t::elaborate(Design*des, PClass*pclass)
|
||||
{
|
||||
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
||||
; cur != pclass->funcs.end() ; ++ cur) {
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": netclass_t::elaborate: "
|
||||
<< "Elaborate class " << scope_path(class_scope_)
|
||||
<< " function method " << cur->first << endl;
|
||||
}
|
||||
|
||||
NetScope*scope = class_scope_->child( hname_t(cur->first) );
|
||||
ivl_assert(*cur->second, scope);
|
||||
cur->second->elaborate(des, scope);
|
||||
}
|
||||
|
||||
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
||||
; cur != pclass->tasks.end() ; ++ cur) {
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": netclass_t::elaborate: "
|
||||
<< "Elaborate class " << scope_path(class_scope_)
|
||||
<< " task method " << cur->first << endl;
|
||||
}
|
||||
|
||||
NetScope*scope = class_scope_->child( hname_t(cur->first) );
|
||||
ivl_assert(*cur->second, scope);
|
||||
cur->second->elaborate(des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
{
|
||||
if (direct_nested_)
|
||||
|
|
|
|||
48
net_scope.cc
48
net_scope.cc
|
|
@ -50,6 +50,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
|
|||
in_final_ = false;
|
||||
|
||||
if (up) {
|
||||
assert(t!=CLASS);
|
||||
need_const_func_ = up->need_const_func_;
|
||||
is_const_func_ = up->is_const_func_;
|
||||
time_unit_ = up->time_unit();
|
||||
|
|
@ -63,7 +64,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
|
|||
time_unit_ = 0;
|
||||
time_prec_ = 0;
|
||||
time_from_timescale_ = false;
|
||||
assert(t==MODULE || t==PACKAGE);
|
||||
assert(t==MODULE || t==PACKAGE || t==CLASS);
|
||||
}
|
||||
|
||||
switch (t) {
|
||||
|
|
@ -77,6 +78,9 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
|
|||
case NetScope::PACKAGE:
|
||||
module_name_ = perm_string();
|
||||
break;
|
||||
case NetScope::CLASS:
|
||||
class_def_ = 0;
|
||||
break;
|
||||
default: /* BEGIN_END and FORK_JOIN, do nothing */
|
||||
break;
|
||||
}
|
||||
|
|
@ -311,9 +315,12 @@ void NetScope::print_type(ostream&stream) const
|
|||
case GENBLOCK:
|
||||
stream << "generate block";
|
||||
break;
|
||||
case PACKAGE:
|
||||
case PACKAGE:
|
||||
stream << "package " << module_name_;
|
||||
break;
|
||||
case CLASS:
|
||||
stream << "class";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -360,6 +367,21 @@ const NetFuncDef* NetScope::func_def() const
|
|||
return func_;
|
||||
}
|
||||
|
||||
void NetScope::set_class_def(netclass_t*def)
|
||||
{
|
||||
assert( type_ == CLASS );
|
||||
assert( class_def_==0 );
|
||||
class_def_ = def;
|
||||
}
|
||||
|
||||
const netclass_t* NetScope::class_def(void) const
|
||||
{
|
||||
if (type_==CLASS)
|
||||
return class_def_;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::set_module_name(perm_string n)
|
||||
{
|
||||
assert(type_==MODULE || type_==PACKAGE);
|
||||
|
|
@ -563,11 +585,27 @@ void NetScope::add_class(netclass_t*net_class)
|
|||
|
||||
netclass_t*NetScope::find_class(perm_string name)
|
||||
{
|
||||
// Special class: The scope itself is the class that we are
|
||||
// looking for. This may happen for example when elaborating
|
||||
// methods within the class.
|
||||
if (type_==CLASS && name_==hname_t(name))
|
||||
return class_def_;
|
||||
|
||||
// Look for the class that directly within this scope.
|
||||
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
|
||||
if (cur == classes_.end())
|
||||
return 0;
|
||||
else
|
||||
if (cur != classes_.end())
|
||||
return cur->second;
|
||||
|
||||
// If this is a module scope, then look no further.
|
||||
if (type_==MODULE)
|
||||
return 0;
|
||||
|
||||
// If there is no further to look, ...
|
||||
if (up_ == 0)
|
||||
return 0;
|
||||
|
||||
// Try looking up for the class.
|
||||
return up_->find_class(name);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
17
netclass.cc
17
netclass.cc
|
|
@ -18,12 +18,13 @@
|
|||
*/
|
||||
|
||||
# include "netclass.h"
|
||||
# include "netlist.h"
|
||||
# include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
netclass_t::netclass_t(perm_string name)
|
||||
: name_(name)
|
||||
: name_(name), class_scope_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -47,6 +48,12 @@ bool netclass_t::set_property(perm_string pname, ivl_type_s*ptype)
|
|||
return true;
|
||||
}
|
||||
|
||||
void netclass_t::set_class_scope(NetScope*class_scope)
|
||||
{
|
||||
assert(class_scope_ == 0);
|
||||
class_scope_ = class_scope;
|
||||
}
|
||||
|
||||
ivl_variable_type_t netclass_t::base_type() const
|
||||
{
|
||||
return IVL_VT_CLASS;
|
||||
|
|
@ -84,3 +91,11 @@ ivl_type_t netclass_t::get_prop_type(size_t idx) const
|
|||
assert(idx < property_table_.size());
|
||||
return property_table_[idx].type;
|
||||
}
|
||||
|
||||
NetScope*netclass_t::method_from_name(perm_string name)
|
||||
{
|
||||
NetScope*task = class_scope_->child( hname_t(name) );
|
||||
if (task == 0) return 0;
|
||||
return task;
|
||||
|
||||
}
|
||||
|
|
|
|||
20
netclass.h
20
netclass.h
|
|
@ -22,8 +22,13 @@
|
|||
# include "LineInfo.h"
|
||||
# include "ivl_target.h"
|
||||
# include "nettypes.h"
|
||||
# include <iostream>
|
||||
# include <map>
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class PClass;
|
||||
|
||||
class netclass_t : public ivl_type_s {
|
||||
public:
|
||||
netclass_t(perm_string class_name);
|
||||
|
|
@ -34,6 +39,10 @@ class netclass_t : public ivl_type_s {
|
|||
// present, then return false.
|
||||
bool set_property(perm_string pname, ivl_type_s*ptype);
|
||||
|
||||
// Set the scope for the class. The scope has no parents and
|
||||
// is used for the elaboration of methods (tasks/functions).
|
||||
void set_class_scope(NetScope*cscope);
|
||||
|
||||
// As an ivl_type_s object, the netclass is always an
|
||||
// ivl_VT_CLASS object.
|
||||
ivl_variable_type_t base_type() const;
|
||||
|
|
@ -49,6 +58,14 @@ class netclass_t : public ivl_type_s {
|
|||
|
||||
int property_idx_from_name(perm_string pname) const;
|
||||
|
||||
// The task method scopes from the method name.
|
||||
NetScope*method_from_name(perm_string mname);
|
||||
|
||||
void elaborate_sig(Design*des, PClass*pclass);
|
||||
void elaborate(Design*des, PClass*pclass);
|
||||
|
||||
void dump_scope(ostream&fd) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
// Map properrty names to property table index.
|
||||
|
|
@ -59,6 +76,9 @@ class netclass_t : public ivl_type_s {
|
|||
ivl_type_s* type;
|
||||
};
|
||||
std::vector<prop_t> property_table_;
|
||||
|
||||
// This holds task/function definitions for methods.
|
||||
NetScope*class_scope_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
13
netlist.cc
13
netlist.cc
|
|
@ -2606,7 +2606,7 @@ unsigned NetUReduce::width() const
|
|||
return width_;
|
||||
}
|
||||
|
||||
NetTaskDef::NetTaskDef(NetScope*n, const svector<NetNet*>&po)
|
||||
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po)
|
||||
: scope_(n), proc_(0), ports_(po)
|
||||
{
|
||||
}
|
||||
|
|
@ -2624,20 +2624,15 @@ void NetTaskDef::set_proc(NetProc*p)
|
|||
|
||||
unsigned NetTaskDef::port_count() const
|
||||
{
|
||||
return ports_.count();
|
||||
return ports_.size();
|
||||
}
|
||||
|
||||
NetNet* NetTaskDef::port(unsigned idx) const
|
||||
{
|
||||
assert(idx < ports_.count());
|
||||
assert(idx < ports_.size());
|
||||
return ports_[idx];
|
||||
}
|
||||
#if 0
|
||||
const string& NetTaskDef::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
#endif
|
||||
|
||||
const NetScope* NetTaskDef::scope() const
|
||||
{
|
||||
return scope_;
|
||||
|
|
|
|||
|
|
@ -764,7 +764,7 @@ class NetNet : public NetObj, public PortType {
|
|||
class NetScope : public Attrib {
|
||||
|
||||
public:
|
||||
enum TYPE { MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE };
|
||||
enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE };
|
||||
|
||||
/* Create a new scope, and attach it to the given parent. The
|
||||
name is expected to have been permallocated. */
|
||||
|
|
@ -858,6 +858,7 @@ class NetScope : public Attrib {
|
|||
|
||||
void set_task_def(NetTaskDef*);
|
||||
void set_func_def(NetFuncDef*);
|
||||
void set_class_def(netclass_t*);
|
||||
void set_module_name(perm_string);
|
||||
|
||||
NetTaskDef* task_def();
|
||||
|
|
@ -919,6 +920,7 @@ class NetScope : public Attrib {
|
|||
|
||||
const NetTaskDef* task_def() const;
|
||||
const NetFuncDef* func_def() const;
|
||||
const netclass_t* class_def() const;
|
||||
|
||||
/* If the scope represents a module instance, the module_name
|
||||
is the name of the module itself. */
|
||||
|
|
@ -1083,6 +1085,7 @@ class NetScope : public Attrib {
|
|||
union {
|
||||
NetTaskDef*task_;
|
||||
NetFuncDef*func_;
|
||||
netclass_t*class_def_;
|
||||
};
|
||||
const PFunction*func_pform_;
|
||||
unsigned elab_stage_;
|
||||
|
|
@ -3275,7 +3278,7 @@ class NetSTask : public NetProc {
|
|||
class NetTaskDef {
|
||||
|
||||
public:
|
||||
NetTaskDef(NetScope*n, const svector<NetNet*>&po);
|
||||
NetTaskDef(NetScope*n, const vector<NetNet*>&po);
|
||||
~NetTaskDef();
|
||||
|
||||
void set_proc(NetProc*p);
|
||||
|
|
@ -3293,7 +3296,7 @@ class NetTaskDef {
|
|||
private:
|
||||
NetScope*scope_;
|
||||
NetProc*proc_;
|
||||
svector<NetNet*>ports_;
|
||||
vector<NetNet*>ports_;
|
||||
|
||||
private: // not implemented
|
||||
NetTaskDef(const NetTaskDef&);
|
||||
|
|
|
|||
10
parse.y
10
parse.y
|
|
@ -1032,7 +1032,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
|||
{ current_function->set_ports($7);
|
||||
current_function->set_return($3);
|
||||
current_function_set_statement($8? @8 : @4, $8);
|
||||
pform_set_this_class(current_function);
|
||||
pform_set_this_class(@4, current_function);
|
||||
pform_pop_scope();
|
||||
current_function = 0;
|
||||
}
|
||||
|
|
@ -1059,7 +1059,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
|||
{ current_function->set_ports($7);
|
||||
current_function->set_return($3);
|
||||
current_function_set_statement($11? @11 : @4, $11);
|
||||
pform_set_this_class(current_function);
|
||||
pform_set_this_class(@4, current_function);
|
||||
pform_pop_scope();
|
||||
current_function = 0;
|
||||
if ($7==0 && !gn_system_verilog()) {
|
||||
|
|
@ -1519,7 +1519,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
K_endtask
|
||||
{ current_task->set_ports($6);
|
||||
current_task_set_statement(@3, $7);
|
||||
pform_set_this_class(current_task);
|
||||
pform_set_this_class(@3, current_task);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
|
||||
|
|
@ -1553,7 +1553,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
K_endtask
|
||||
{ current_task->set_ports($6);
|
||||
current_task_set_statement(@3, $10);
|
||||
pform_set_this_class(current_task);
|
||||
pform_set_this_class(@3, current_task);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
if ($10) delete $10;
|
||||
|
|
@ -1583,7 +1583,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
K_endtask
|
||||
{ current_task->set_ports(0);
|
||||
current_task_set_statement(@3, $9);
|
||||
pform_set_this_class(current_task);
|
||||
pform_set_this_class(@3, current_task);
|
||||
if (! current_task->method_of()) {
|
||||
cerr << @3 << ": warning: task definition for \"" << $3
|
||||
<< "\" has an empty port declaration list!" << endl;
|
||||
|
|
|
|||
36
pform.cc
36
pform.cc
|
|
@ -2346,6 +2346,35 @@ vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
|||
return res;
|
||||
}
|
||||
|
||||
static vector<PWire*>*do_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t var_type,
|
||||
data_type_t*data_type,
|
||||
list<perm_string>*names)
|
||||
{
|
||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
assert(names);
|
||||
vector<PWire*>*res = new vector<PWire*>(0);
|
||||
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++cur) {
|
||||
perm_string name = *cur;
|
||||
PWire*curw = pform_get_wire_in_scope(name);
|
||||
if (curw) {
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, var_type);
|
||||
FILE_NAME(curw, loc);
|
||||
curw->set_data_type(data_type);
|
||||
pform_put_wire_in_scope(name, curw);
|
||||
}
|
||||
|
||||
res->push_back(curw);
|
||||
}
|
||||
delete names;
|
||||
return res;
|
||||
}
|
||||
|
||||
vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
data_type_t*vtype,
|
||||
|
|
@ -2370,8 +2399,11 @@ vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
|||
true, 0, names);
|
||||
}
|
||||
|
||||
VLerror(loc, "sorry: Given type not supported here.");
|
||||
return 0;
|
||||
if (class_type_t*class_type = dynamic_cast<class_type_t*> (vtype)) {
|
||||
return do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
|
||||
}
|
||||
|
||||
return do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
2
pform.h
2
pform.h
|
|
@ -185,7 +185,7 @@ extern void pform_class_property(const struct vlltype&loc,
|
|||
property_qualifier_t pq,
|
||||
data_type_t*data_type,
|
||||
std::list<decl_assignment_t*>*decls);
|
||||
extern void pform_set_this_class(PTaskFunc*net);
|
||||
extern void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net);
|
||||
|
||||
extern void pform_end_class_declaration(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -911,12 +911,7 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
|||
if (method_of())
|
||||
out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl;
|
||||
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->size() ; idx += 1) {
|
||||
out << setw(ind) << "";
|
||||
out << "input ";
|
||||
out << (*ports_)[idx]->basename() << ";" << endl;
|
||||
}
|
||||
dump_ports_(out, ind);
|
||||
|
||||
dump_parameters_(out, ind);
|
||||
|
||||
|
|
@ -951,35 +946,7 @@ void PTask::dump(ostream&out, unsigned ind) const
|
|||
out << pscope_name() << ";" << endl;
|
||||
if (method_of())
|
||||
out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl;
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->size() ; idx += 1) {
|
||||
if ((*ports_)[idx] == 0) {
|
||||
out << setw(ind) << "" << "ERROR PORT" << endl;
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
case NetNet::PIMPLICIT:
|
||||
out << "PIMPLICIT";
|
||||
break;
|
||||
case NetNet::NOT_A_PORT:
|
||||
out << "NOT_A_PORT";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
out << (*ports_)[idx]->basename() << ";" << endl;
|
||||
}
|
||||
dump_ports_(out, ind);
|
||||
|
||||
dump_parameters_(out, ind);
|
||||
|
||||
|
|
@ -995,6 +962,42 @@ void PTask::dump(ostream&out, unsigned ind) const
|
|||
out << setw(ind) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PTaskFunc::dump_ports_(std::ostream&out, unsigned ind) const
|
||||
{
|
||||
if (ports_ == 0)
|
||||
return;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports_->size() ; idx += 1) {
|
||||
if (ports_->at(idx) == 0) {
|
||||
out << setw(ind) << "" << "ERROR PORT" << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
out << setw(ind) << "";
|
||||
switch (ports_->at(idx)->get_port_type()) {
|
||||
case NetNet::PINPUT:
|
||||
out << "input ";
|
||||
break;
|
||||
case NetNet::POUTPUT:
|
||||
out << "output ";
|
||||
break;
|
||||
case NetNet::PINOUT:
|
||||
out << "inout ";
|
||||
break;
|
||||
case NetNet::PIMPLICIT:
|
||||
out << "PIMPLICIT";
|
||||
break;
|
||||
case NetNet::NOT_A_PORT:
|
||||
out << "NOT_A_PORT";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
out << ports_->at(idx)->basename() << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PTrigger::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "-> " << event_ << ";" << endl;
|
||||
|
|
|
|||
|
|
@ -72,12 +72,23 @@ void pform_class_property(const struct vlltype&loc,
|
|||
}
|
||||
}
|
||||
|
||||
void pform_set_this_class(PTaskFunc*net)
|
||||
void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net)
|
||||
{
|
||||
if (pform_cur_class == 0)
|
||||
return;
|
||||
|
||||
net->set_this(pform_cur_class->type);
|
||||
list<perm_string>*this_name = new list<perm_string>;
|
||||
this_name->push_back(perm_string::literal("@"));
|
||||
vector<PWire*>*this_port = pform_make_task_ports(loc, NetNet::PINPUT,
|
||||
pform_cur_class->type,
|
||||
this_name);
|
||||
// The pform_make_task_ports() function deletes the this_name
|
||||
// object.
|
||||
|
||||
PWire*this_wire = this_port->at(0);
|
||||
delete this_port;
|
||||
|
||||
net->set_this(pform_cur_class->type, this_wire);
|
||||
}
|
||||
|
||||
void pform_end_class_declaration(void)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
# include <cassert>
|
||||
# include <cstdlib>
|
||||
# include "ivl_alloc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* This is a little convenience function for converting a NetExpr
|
||||
|
|
@ -562,7 +563,8 @@ void dll_target::expr_ufunc(const NetEUFunc*net)
|
|||
FILE_NAME(expr, net);
|
||||
|
||||
expr->u_.ufunc_.def = lookup_scope_(net->func());
|
||||
assert(expr->u_.ufunc_.def->type_ == IVL_SCT_FUNCTION);
|
||||
ivl_assert(*net, expr->u_.ufunc_.def);
|
||||
ivl_assert(*net, expr->u_.ufunc_.def->type_ == IVL_SCT_FUNCTION);
|
||||
|
||||
unsigned cnt = net->parm_count();
|
||||
expr->u_.ufunc_.parms = cnt;
|
||||
|
|
|
|||
Loading…
Reference in New Issue