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;
|
std::list<long>&prefix_indices) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NetAssign_*elaborate_lval_method_class_member_(Design*, NetScope*) const;
|
||||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
|
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
|
||||||
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
|
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
|
||||||
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
|
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
|
||||||
|
|
@ -449,6 +450,11 @@ class PEIdent : public PExpr {
|
||||||
NetScope*found,
|
NetScope*found,
|
||||||
bool need_const) const;
|
bool need_const) const;
|
||||||
|
|
||||||
|
NetExpr*elaborate_expr_class_member_(Design*des,
|
||||||
|
NetScope*scope,
|
||||||
|
unsigned expr_wid,
|
||||||
|
unsigned flags) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
bool bidirectional_flag) const;
|
bool bidirectional_flag) const;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
|
||||||
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
|
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__;
|
is_auto_ = is_auto__;
|
||||||
return_type_.type = PTF_NONE;
|
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)
|
void PFunction::set_statement(Statement*s)
|
||||||
{
|
{
|
||||||
assert(s != 0);
|
assert(s != 0);
|
||||||
|
|
|
||||||
29
PTask.cc
29
PTask.cc
|
|
@ -22,7 +22,7 @@
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
|
||||||
PTaskFunc::PTaskFunc(perm_string n, LexicalScope*p)
|
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);
|
assert(this_type_ == 0);
|
||||||
this_type_ = type;
|
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__)
|
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__;
|
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)
|
void PTask::set_statement(Statement*s)
|
||||||
{
|
{
|
||||||
assert(statement_ == 0);
|
assert(statement_ == 0);
|
||||||
|
|
|
||||||
16
PTask.h
16
PTask.h
|
|
@ -26,6 +26,7 @@
|
||||||
# include <vector>
|
# include <vector>
|
||||||
# include <list>
|
# include <list>
|
||||||
class Design;
|
class Design;
|
||||||
|
class NetNet;
|
||||||
class NetScope;
|
class NetScope;
|
||||||
class PWire;
|
class PWire;
|
||||||
class Statement;
|
class Statement;
|
||||||
|
|
@ -56,14 +57,23 @@ class PTaskFunc : public PScope, public LineInfo {
|
||||||
PTaskFunc(perm_string name, LexicalScope*parent);
|
PTaskFunc(perm_string name, LexicalScope*parent);
|
||||||
~PTaskFunc();
|
~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
|
// If this task is a method of a class, this returns a pointer
|
||||||
// to the class type.
|
// to the class type.
|
||||||
inline class_type_t* method_of() const { return this_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:
|
private:
|
||||||
class_type_t*this_type_;
|
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);
|
explicit PTask(perm_string name, LexicalScope*parent, bool is_auto);
|
||||||
~PTask();
|
~PTask();
|
||||||
|
|
||||||
void set_ports(std::vector<PWire *>*p);
|
|
||||||
void set_statement(Statement *s);
|
void set_statement(Statement *s);
|
||||||
|
|
||||||
// Tasks introduce scope, to need to be handled during the
|
// Tasks introduce scope, to need to be handled during the
|
||||||
|
|
@ -95,7 +104,6 @@ class PTask : public PTaskFunc {
|
||||||
void dump(ostream&, unsigned) const;
|
void dump(ostream&, unsigned) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<PWire*>*ports_;
|
|
||||||
Statement*statement_;
|
Statement*statement_;
|
||||||
bool is_auto_;
|
bool is_auto_;
|
||||||
|
|
||||||
|
|
@ -117,7 +125,6 @@ class PFunction : public PTaskFunc {
|
||||||
explicit PFunction(perm_string name, LexicalScope*parent, bool is_auto);
|
explicit PFunction(perm_string name, LexicalScope*parent, bool is_auto);
|
||||||
~PFunction();
|
~PFunction();
|
||||||
|
|
||||||
void set_ports(std::vector<PWire *>*p);
|
|
||||||
void set_statement(Statement *s);
|
void set_statement(Statement *s);
|
||||||
void set_return(PTaskFuncArg t);
|
void set_return(PTaskFuncArg t);
|
||||||
|
|
||||||
|
|
@ -135,7 +142,6 @@ class PFunction : public PTaskFunc {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PTaskFuncArg return_type_;
|
PTaskFuncArg return_type_;
|
||||||
std::vector<PWire *> *ports_;
|
|
||||||
Statement *statement_;
|
Statement *statement_;
|
||||||
bool is_auto_;
|
bool is_auto_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "compiler.h"
|
# include "compiler.h"
|
||||||
# include "discipline.h"
|
# include "discipline.h"
|
||||||
|
# include "netclass.h"
|
||||||
# include "netdarray.h"
|
# include "netdarray.h"
|
||||||
# include "netvector.h"
|
# include "netvector.h"
|
||||||
# include "ivl_assert.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;
|
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) << "";
|
o << setw(ind+4) << "";
|
||||||
assert(ports_[idx]);
|
assert(ports_[idx]);
|
||||||
switch (ports_[idx]->port_type()) {
|
switch (ports_[idx]->port_type()) {
|
||||||
|
|
@ -767,7 +768,10 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||||
o << ports_[idx]->name() << ";" << endl;
|
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;
|
o << setw(ind) << "" << "endtask" << endl;
|
||||||
}
|
}
|
||||||
|
|
@ -1140,7 +1144,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||||
if (statement_)
|
if (statement_)
|
||||||
statement_->dump(o, ind+2);
|
statement_->dump(o, ind+2);
|
||||||
else
|
else
|
||||||
o << setw(ind+2) << "" << "// NO STATEMENT" << endl;
|
o << setw(ind+2) << "" << "MISSING PROCEDURAL CODE" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetPDelay::dump(ostream&o, unsigned ind) const
|
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);
|
statement_->dump(o, ind+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void netclass_t::dump_scope(ostream&fd) const
|
||||||
|
{
|
||||||
|
class_scope_->dump(fd);
|
||||||
|
}
|
||||||
|
|
||||||
void NetScope::dump(ostream&o) const
|
void NetScope::dump(ostream&o) const
|
||||||
{
|
{
|
||||||
/* This is a constructed hierarchical name. */
|
/* 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()
|
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||||
; cur != children_.end() ; ++ cur )
|
; cur != children_.end() ; ++ cur )
|
||||||
cur->second->dump(o);
|
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
|
void NetSTask::dump(ostream&o, unsigned ind) const
|
||||||
|
|
@ -1588,7 +1602,7 @@ void NetETernary::dump(ostream&o) const
|
||||||
|
|
||||||
void NetEUFunc::dump(ostream&o) const
|
void NetEUFunc::dump(ostream&o) const
|
||||||
{
|
{
|
||||||
o << func_->basename() << "(";
|
o << scope_path(func_) << "(";
|
||||||
if (! parms_.empty()) {
|
if (! parms_.empty()) {
|
||||||
parms_[0]->dump(o);
|
parms_[0]->dump(o);
|
||||||
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
|
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_;
|
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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2699,6 +2742,51 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
return tmp;
|
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
|
* 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
|
* 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;
|
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 (path_.size() > 1) {
|
||||||
if (NEED_CONST & flags) {
|
if (NEED_CONST & flags) {
|
||||||
cerr << get_fileline() << ": error: A hierarchical reference"
|
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;
|
NetEvent* eve = 0;
|
||||||
perm_string method_name;
|
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);
|
symbol_search(this, des, scope, path_, reg, par, eve);
|
||||||
|
|
||||||
/* If the signal is not found, check to see if this is a
|
/* 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;
|
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,
|
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
NetNet*reg) const
|
NetNet*reg) const
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,18 @@ static void elaborate_scope_class(Design*des, NetScope*scope,
|
||||||
class_type_t*use_type = pclass->type;
|
class_type_t*use_type = pclass->type;
|
||||||
netclass_t*use_class = new netclass_t(use_type->name);
|
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()
|
for (map<perm_string, data_type_t*>::iterator cur = use_type->properties.begin()
|
||||||
; cur != use_type->properties.end() ; ++ cur) {
|
; cur != use_type->properties.end() ; ++ cur) {
|
||||||
ivl_type_s*tmp = cur->second->elaborate_type(des, scope);
|
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()
|
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
||||||
; cur != pclass->tasks.end() ; ++cur) {
|
; 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()
|
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
||||||
; cur != pclass->funcs.end() ; ++cur) {
|
; 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);
|
scope->add_class(use_class);
|
||||||
|
|
|
||||||
209
elab_sig.cc
209
elab_sig.cc
|
|
@ -25,6 +25,7 @@
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
||||||
# include "Module.h"
|
# include "Module.h"
|
||||||
|
# include "PClass.h"
|
||||||
# include "PExpr.h"
|
# include "PExpr.h"
|
||||||
# include "PGate.h"
|
# include "PGate.h"
|
||||||
# include "PGenerate.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
|
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_funcs(des, scope, funcs);
|
||||||
elaborate_sig_tasks(des, scope, tasks);
|
elaborate_sig_tasks(des, scope, tasks);
|
||||||
|
elaborate_sig_classes(des, scope, classes);
|
||||||
|
|
||||||
// initial and always blocks may contain begin-end and
|
// initial and always blocks may contain begin-end and
|
||||||
// fork-join blocks that can introduce scopes. Therefore, I
|
// fork-join blocks that can introduce scopes. Therefore, I
|
||||||
|
|
@ -278,6 +289,34 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
return flag;
|
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
|
bool PGate::elaborate_sig(Design*, NetScope*) const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -475,17 +514,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
elaborate_sig_wires_(des, scope);
|
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;
|
NetNet*ret_sig = 0;
|
||||||
netvector_t*ret_vec = 0;
|
netvector_t*ret_vec = 0;
|
||||||
|
|
||||||
|
|
@ -621,63 +649,15 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (ports_) {
|
/* If we do not have any ports or a return type this
|
||||||
cerr << get_fileline() << ": internal error: I don't know "
|
* is probably a bad function definition. */
|
||||||
<< "how to deal with return type of function "
|
cerr << get_fileline() << ": error: Bad definition for "
|
||||||
<< scope->basename() << "." << endl;
|
<< "function " << scope->basename() << "?" << endl;
|
||||||
} else {
|
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);
|
vector<NetNet*>ports;
|
||||||
|
elaborate_sig_ports_(des, scope, ports);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NetFuncDef*def = 0;
|
NetFuncDef*def = 0;
|
||||||
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
|
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);
|
elaborate_sig_wires_(des, scope);
|
||||||
|
|
||||||
svector<NetNet*>ports (ports_? ports_->size() : 0);
|
vector<NetNet*>ports;
|
||||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
elaborate_sig_ports_(des, scope, ports);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetTaskDef*def = new NetTaskDef(scope, ports);
|
NetTaskDef*def = new NetTaskDef(scope, ports);
|
||||||
scope->set_task_def(def);
|
scope->set_task_def(def);
|
||||||
|
|
||||||
|
|
@ -739,6 +700,68 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
statement_->elaborate_sig(des, scope);
|
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
|
void PBlock::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
NetScope*my_scope = scope;
|
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
|
// do right now is locate the netclass_t object for the
|
||||||
// class, and use that to build the net.
|
// class, and use that to build the net.
|
||||||
netclass_t*use_type = locate_class_type(des, scope, class_type);
|
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)
|
// (No arrays of classes)
|
||||||
list<netrange_t> use_unpacked;
|
list<netrange_t> use_unpacked;
|
||||||
sig = new NetNet(scope, name_, wtype, use_unpacked, use_type);
|
sig = new NetNet(scope, name_, wtype, use_unpacked, use_type);
|
||||||
|
|
|
||||||
64
elaborate.cc
64
elaborate.cc
|
|
@ -31,6 +31,7 @@
|
||||||
# include <sstream>
|
# include <sstream>
|
||||||
# include <list>
|
# include <list>
|
||||||
# include "pform.h"
|
# include "pform.h"
|
||||||
|
# include "PClass.h"
|
||||||
# include "PEvent.h"
|
# include "PEvent.h"
|
||||||
# include "PGenerate.h"
|
# include "PGenerate.h"
|
||||||
# include "PPackage.h"
|
# include "PPackage.h"
|
||||||
|
|
@ -3325,6 +3326,20 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
|
||||||
return sys;
|
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;
|
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
|
* When a module is instantiated, it creates the scope then uses this
|
||||||
* method to elaborate the contents of the module.
|
* 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.
|
// the signals so that the tasks can reference them.
|
||||||
elaborate_tasks(des, scope, tasks);
|
elaborate_tasks(des, scope, tasks);
|
||||||
|
|
||||||
|
// Elaboate class definitions.
|
||||||
|
elaborate_classes(des, scope, classes);
|
||||||
|
|
||||||
// Get all the gates of the module and elaborate them by
|
// Get all the gates of the module and elaborate them by
|
||||||
// connecting them to the signals. The gate may be simple or
|
// connecting them to the signals. The gate may be simple or
|
||||||
// complex.
|
// complex.
|
||||||
|
|
@ -4730,6 +4758,42 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||||
return result_flag;
|
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
|
bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||||
{
|
{
|
||||||
if (direct_nested_)
|
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;
|
in_final_ = false;
|
||||||
|
|
||||||
if (up) {
|
if (up) {
|
||||||
|
assert(t!=CLASS);
|
||||||
need_const_func_ = up->need_const_func_;
|
need_const_func_ = up->need_const_func_;
|
||||||
is_const_func_ = up->is_const_func_;
|
is_const_func_ = up->is_const_func_;
|
||||||
time_unit_ = up->time_unit();
|
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_unit_ = 0;
|
||||||
time_prec_ = 0;
|
time_prec_ = 0;
|
||||||
time_from_timescale_ = false;
|
time_from_timescale_ = false;
|
||||||
assert(t==MODULE || t==PACKAGE);
|
assert(t==MODULE || t==PACKAGE || t==CLASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (t) {
|
switch (t) {
|
||||||
|
|
@ -77,6 +78,9 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
|
||||||
case NetScope::PACKAGE:
|
case NetScope::PACKAGE:
|
||||||
module_name_ = perm_string();
|
module_name_ = perm_string();
|
||||||
break;
|
break;
|
||||||
|
case NetScope::CLASS:
|
||||||
|
class_def_ = 0;
|
||||||
|
break;
|
||||||
default: /* BEGIN_END and FORK_JOIN, do nothing */
|
default: /* BEGIN_END and FORK_JOIN, do nothing */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -311,9 +315,12 @@ void NetScope::print_type(ostream&stream) const
|
||||||
case GENBLOCK:
|
case GENBLOCK:
|
||||||
stream << "generate block";
|
stream << "generate block";
|
||||||
break;
|
break;
|
||||||
case PACKAGE:
|
case PACKAGE:
|
||||||
stream << "package " << module_name_;
|
stream << "package " << module_name_;
|
||||||
break;
|
break;
|
||||||
|
case CLASS:
|
||||||
|
stream << "class";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,6 +367,21 @@ const NetFuncDef* NetScope::func_def() const
|
||||||
return func_;
|
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)
|
void NetScope::set_module_name(perm_string n)
|
||||||
{
|
{
|
||||||
assert(type_==MODULE || type_==PACKAGE);
|
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)
|
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);
|
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
|
||||||
if (cur == classes_.end())
|
if (cur != classes_.end())
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return cur->second;
|
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 "netclass.h"
|
||||||
|
# include "netlist.h"
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
netclass_t::netclass_t(perm_string name)
|
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;
|
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
|
ivl_variable_type_t netclass_t::base_type() const
|
||||||
{
|
{
|
||||||
return IVL_VT_CLASS;
|
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());
|
assert(idx < property_table_.size());
|
||||||
return property_table_[idx].type;
|
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 "LineInfo.h"
|
||||||
# include "ivl_target.h"
|
# include "ivl_target.h"
|
||||||
# include "nettypes.h"
|
# include "nettypes.h"
|
||||||
|
# include <iostream>
|
||||||
# include <map>
|
# include <map>
|
||||||
|
|
||||||
|
class Design;
|
||||||
|
class NetScope;
|
||||||
|
class PClass;
|
||||||
|
|
||||||
class netclass_t : public ivl_type_s {
|
class netclass_t : public ivl_type_s {
|
||||||
public:
|
public:
|
||||||
netclass_t(perm_string class_name);
|
netclass_t(perm_string class_name);
|
||||||
|
|
@ -34,6 +39,10 @@ class netclass_t : public ivl_type_s {
|
||||||
// present, then return false.
|
// present, then return false.
|
||||||
bool set_property(perm_string pname, ivl_type_s*ptype);
|
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
|
// As an ivl_type_s object, the netclass is always an
|
||||||
// ivl_VT_CLASS object.
|
// ivl_VT_CLASS object.
|
||||||
ivl_variable_type_t base_type() const;
|
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;
|
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:
|
private:
|
||||||
perm_string name_;
|
perm_string name_;
|
||||||
// Map properrty names to property table index.
|
// Map properrty names to property table index.
|
||||||
|
|
@ -59,6 +76,9 @@ class netclass_t : public ivl_type_s {
|
||||||
ivl_type_s* type;
|
ivl_type_s* type;
|
||||||
};
|
};
|
||||||
std::vector<prop_t> property_table_;
|
std::vector<prop_t> property_table_;
|
||||||
|
|
||||||
|
// This holds task/function definitions for methods.
|
||||||
|
NetScope*class_scope_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
13
netlist.cc
13
netlist.cc
|
|
@ -2606,7 +2606,7 @@ unsigned NetUReduce::width() const
|
||||||
return width_;
|
return width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetTaskDef::NetTaskDef(NetScope*n, const svector<NetNet*>&po)
|
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po)
|
||||||
: scope_(n), proc_(0), ports_(po)
|
: scope_(n), proc_(0), ports_(po)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -2624,20 +2624,15 @@ void NetTaskDef::set_proc(NetProc*p)
|
||||||
|
|
||||||
unsigned NetTaskDef::port_count() const
|
unsigned NetTaskDef::port_count() const
|
||||||
{
|
{
|
||||||
return ports_.count();
|
return ports_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetNet* NetTaskDef::port(unsigned idx) const
|
NetNet* NetTaskDef::port(unsigned idx) const
|
||||||
{
|
{
|
||||||
assert(idx < ports_.count());
|
assert(idx < ports_.size());
|
||||||
return ports_[idx];
|
return ports_[idx];
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
const string& NetTaskDef::name() const
|
|
||||||
{
|
|
||||||
return name_;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
const NetScope* NetTaskDef::scope() const
|
const NetScope* NetTaskDef::scope() const
|
||||||
{
|
{
|
||||||
return scope_;
|
return scope_;
|
||||||
|
|
|
||||||
|
|
@ -764,7 +764,7 @@ class NetNet : public NetObj, public PortType {
|
||||||
class NetScope : public Attrib {
|
class NetScope : public Attrib {
|
||||||
|
|
||||||
public:
|
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
|
/* Create a new scope, and attach it to the given parent. The
|
||||||
name is expected to have been permallocated. */
|
name is expected to have been permallocated. */
|
||||||
|
|
@ -858,6 +858,7 @@ class NetScope : public Attrib {
|
||||||
|
|
||||||
void set_task_def(NetTaskDef*);
|
void set_task_def(NetTaskDef*);
|
||||||
void set_func_def(NetFuncDef*);
|
void set_func_def(NetFuncDef*);
|
||||||
|
void set_class_def(netclass_t*);
|
||||||
void set_module_name(perm_string);
|
void set_module_name(perm_string);
|
||||||
|
|
||||||
NetTaskDef* task_def();
|
NetTaskDef* task_def();
|
||||||
|
|
@ -919,6 +920,7 @@ class NetScope : public Attrib {
|
||||||
|
|
||||||
const NetTaskDef* task_def() const;
|
const NetTaskDef* task_def() const;
|
||||||
const NetFuncDef* func_def() const;
|
const NetFuncDef* func_def() const;
|
||||||
|
const netclass_t* class_def() const;
|
||||||
|
|
||||||
/* If the scope represents a module instance, the module_name
|
/* If the scope represents a module instance, the module_name
|
||||||
is the name of the module itself. */
|
is the name of the module itself. */
|
||||||
|
|
@ -1083,6 +1085,7 @@ class NetScope : public Attrib {
|
||||||
union {
|
union {
|
||||||
NetTaskDef*task_;
|
NetTaskDef*task_;
|
||||||
NetFuncDef*func_;
|
NetFuncDef*func_;
|
||||||
|
netclass_t*class_def_;
|
||||||
};
|
};
|
||||||
const PFunction*func_pform_;
|
const PFunction*func_pform_;
|
||||||
unsigned elab_stage_;
|
unsigned elab_stage_;
|
||||||
|
|
@ -3275,7 +3278,7 @@ class NetSTask : public NetProc {
|
||||||
class NetTaskDef {
|
class NetTaskDef {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NetTaskDef(NetScope*n, const svector<NetNet*>&po);
|
NetTaskDef(NetScope*n, const vector<NetNet*>&po);
|
||||||
~NetTaskDef();
|
~NetTaskDef();
|
||||||
|
|
||||||
void set_proc(NetProc*p);
|
void set_proc(NetProc*p);
|
||||||
|
|
@ -3293,7 +3296,7 @@ class NetTaskDef {
|
||||||
private:
|
private:
|
||||||
NetScope*scope_;
|
NetScope*scope_;
|
||||||
NetProc*proc_;
|
NetProc*proc_;
|
||||||
svector<NetNet*>ports_;
|
vector<NetNet*>ports_;
|
||||||
|
|
||||||
private: // not implemented
|
private: // not implemented
|
||||||
NetTaskDef(const NetTaskDef&);
|
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_ports($7);
|
||||||
current_function->set_return($3);
|
current_function->set_return($3);
|
||||||
current_function_set_statement($8? @8 : @4, $8);
|
current_function_set_statement($8? @8 : @4, $8);
|
||||||
pform_set_this_class(current_function);
|
pform_set_this_class(@4, current_function);
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_function = 0;
|
current_function = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1059,7 +1059,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
{ current_function->set_ports($7);
|
{ current_function->set_ports($7);
|
||||||
current_function->set_return($3);
|
current_function->set_return($3);
|
||||||
current_function_set_statement($11? @11 : @4, $11);
|
current_function_set_statement($11? @11 : @4, $11);
|
||||||
pform_set_this_class(current_function);
|
pform_set_this_class(@4, current_function);
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_function = 0;
|
current_function = 0;
|
||||||
if ($7==0 && !gn_system_verilog()) {
|
if ($7==0 && !gn_system_verilog()) {
|
||||||
|
|
@ -1519,7 +1519,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
K_endtask
|
K_endtask
|
||||||
{ current_task->set_ports($6);
|
{ current_task->set_ports($6);
|
||||||
current_task_set_statement(@3, $7);
|
current_task_set_statement(@3, $7);
|
||||||
pform_set_this_class(current_task);
|
pform_set_this_class(@3, current_task);
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_task = 0;
|
current_task = 0;
|
||||||
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
|
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
|
||||||
|
|
@ -1553,7 +1553,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
K_endtask
|
K_endtask
|
||||||
{ current_task->set_ports($6);
|
{ current_task->set_ports($6);
|
||||||
current_task_set_statement(@3, $10);
|
current_task_set_statement(@3, $10);
|
||||||
pform_set_this_class(current_task);
|
pform_set_this_class(@3, current_task);
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_task = 0;
|
current_task = 0;
|
||||||
if ($10) delete $10;
|
if ($10) delete $10;
|
||||||
|
|
@ -1583,7 +1583,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
K_endtask
|
K_endtask
|
||||||
{ current_task->set_ports(0);
|
{ current_task->set_ports(0);
|
||||||
current_task_set_statement(@3, $9);
|
current_task_set_statement(@3, $9);
|
||||||
pform_set_this_class(current_task);
|
pform_set_this_class(@3, current_task);
|
||||||
if (! current_task->method_of()) {
|
if (! current_task->method_of()) {
|
||||||
cerr << @3 << ": warning: task definition for \"" << $3
|
cerr << @3 << ": warning: task definition for \"" << $3
|
||||||
<< "\" has an empty port declaration list!" << endl;
|
<< "\" 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;
|
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,
|
vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||||
NetNet::PortType pt,
|
NetNet::PortType pt,
|
||||||
data_type_t*vtype,
|
data_type_t*vtype,
|
||||||
|
|
@ -2370,8 +2399,11 @@ vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||||
true, 0, names);
|
true, 0, names);
|
||||||
}
|
}
|
||||||
|
|
||||||
VLerror(loc, "sorry: Given type not supported here.");
|
if (class_type_t*class_type = dynamic_cast<class_type_t*> (vtype)) {
|
||||||
return 0;
|
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,
|
property_qualifier_t pq,
|
||||||
data_type_t*data_type,
|
data_type_t*data_type,
|
||||||
std::list<decl_assignment_t*>*decls);
|
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);
|
extern void pform_end_class_declaration(void);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -911,12 +911,7 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
||||||
if (method_of())
|
if (method_of())
|
||||||
out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl;
|
out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl;
|
||||||
|
|
||||||
if (ports_)
|
dump_ports_(out, ind);
|
||||||
for (unsigned idx = 0 ; idx < ports_->size() ; idx += 1) {
|
|
||||||
out << setw(ind) << "";
|
|
||||||
out << "input ";
|
|
||||||
out << (*ports_)[idx]->basename() << ";" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_parameters_(out, ind);
|
dump_parameters_(out, ind);
|
||||||
|
|
||||||
|
|
@ -951,35 +946,7 @@ void PTask::dump(ostream&out, unsigned ind) const
|
||||||
out << pscope_name() << ";" << endl;
|
out << pscope_name() << ";" << endl;
|
||||||
if (method_of())
|
if (method_of())
|
||||||
out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl;
|
out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl;
|
||||||
if (ports_)
|
dump_ports_(out, ind);
|
||||||
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_parameters_(out, ind);
|
dump_parameters_(out, ind);
|
||||||
|
|
||||||
|
|
@ -995,6 +962,42 @@ void PTask::dump(ostream&out, unsigned ind) const
|
||||||
out << setw(ind) << "" << "/* NOOP */" << endl;
|
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
|
void PTrigger::dump(ostream&out, unsigned ind) const
|
||||||
{
|
{
|
||||||
out << setw(ind) << "" << "-> " << event_ << ";" << endl;
|
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)
|
if (pform_cur_class == 0)
|
||||||
return;
|
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)
|
void pform_end_class_declaration(void)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
# include <cstdlib>
|
# include <cstdlib>
|
||||||
# include "ivl_alloc.h"
|
# include "ivl_alloc.h"
|
||||||
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a little convenience function for converting a NetExpr
|
* 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);
|
FILE_NAME(expr, net);
|
||||||
|
|
||||||
expr->u_.ufunc_.def = lookup_scope_(net->func());
|
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();
|
unsigned cnt = net->parm_count();
|
||||||
expr->u_.ufunc_.parms = cnt;
|
expr->u_.ufunc_.parms = cnt;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue