Handle task/function default expressions in parsing/pform.

This gets it to (but not through) the elaborator.
This commit is contained in:
Stephen Williams 2013-09-13 17:04:25 -07:00
parent d8f945be23
commit 9a116498a2
9 changed files with 58 additions and 34 deletions

View File

@ -30,7 +30,7 @@ PTaskFunc::~PTaskFunc()
{
}
void PTaskFunc::set_ports(vector<PWire*>*p)
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
{
assert(ports_ == 0);
ports_ = p;
@ -43,14 +43,14 @@ void PTaskFunc::set_this(class_type_t*type, PWire*this_wire)
// Push a synthetis argument that is the "this" value.
if (ports_==0)
ports_ = new vector<PWire*>;
ports_ = new vector<pform_tf_port_t>;
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;
ports_->at(0) = pform_tf_port_t(this_wire);
}
PTask::PTask(perm_string name, LexicalScope*parent, bool is_auto__)

View File

@ -39,7 +39,7 @@ class PTaskFunc : public PScope, public LineInfo {
PTaskFunc(perm_string name, LexicalScope*parent);
~PTaskFunc();
void set_ports(std::vector<PWire *>*p);
void set_ports(std::vector<pform_tf_port_t>*p);
void set_this(class_type_t*use_type, PWire*this_wire);
@ -55,7 +55,7 @@ class PTaskFunc : public PScope, public LineInfo {
private:
class_type_t*this_type_;
std::vector<PWire*>*ports_;
std::vector<pform_tf_port_t>*ports_;
};
/*

View File

@ -664,7 +664,7 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
for (size_t idx = 0 ; idx < ports_->size() ; idx += 1) {
perm_string port_name = ports_->at(idx)->basename();
perm_string port_name = ports_->at(idx).port->basename();
ports[idx] = 0;
NetNet*tmp = scope->find_signal(port_name);
@ -678,6 +678,13 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
continue;
}
if (ports_->at(idx).defe != 0) {
cerr << get_fileline() << ": sorry: "
<< "task/function default port expressions not supported."
<< endl;
des->errors += 1;
}
if (tmp->port_type() == NetNet::NOT_A_PORT) {
cerr << get_fileline() << ": internal error: "
<< "task/function " << scope_path(scope)

30
parse.y
View File

@ -339,6 +339,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
list<pair<perm_string,PExpr*> >*port_list;
vector<pform_tf_port_t>* tf_ports;
pform_name_t*pform_name;
ivl_discipline_t discipline;
@ -544,9 +546,9 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <named_pexprs> enum_name_list enum_name
%type <enum_type> enum_data_type
%type <wires> task_item task_item_list task_item_list_opt
%type <wires> tf_port_declaration tf_port_item tf_port_list tf_port_list_opt
%type <wires> function_item function_item_list function_item_list_opt
%type <tf_ports> function_item function_item_list function_item_list_opt
%type <tf_ports> task_item task_item_list task_item_list_opt
%type <tf_ports> tf_port_declaration tf_port_item tf_port_list tf_port_list_opt
%type <named_pexpr> port_name parameter_value_byname
%type <named_pexprs> port_name_list parameter_value_byname_list
@ -1735,7 +1737,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
tf_port_declaration /* IEEE1800-2005: A.2.7 */
: port_direction K_reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
{ vector<PWire*>*tmp = pform_make_task_ports(@1, $1,
{ vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1,
$2 ? IVL_VT_LOGIC :
IVL_VT_NO_TYPE,
$3, $4, $5);
@ -1747,7 +1749,7 @@ tf_port_declaration /* IEEE1800-2005: A.2.7 */
| port_direction K_integer list_of_identifiers ';'
{ list<pform_range_t>*range_stub = make_range_from_width(integer_width);
vector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, true,
vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, true,
range_stub, $3, true);
$$ = tmp;
}
@ -1756,7 +1758,7 @@ tf_port_declaration /* IEEE1800-2005: A.2.7 */
| port_direction K_time list_of_identifiers ';'
{ list<pform_range_t>*range_stub = make_range_from_width(64);
vector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, false,
vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, false,
range_stub, $3);
$$ = tmp;
}
@ -1764,7 +1766,7 @@ tf_port_declaration /* IEEE1800-2005: A.2.7 */
/* Ports can be real or realtime. */
| port_direction real_or_realtime list_of_identifiers ';'
{ vector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_REAL, true,
{ vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1, IVL_VT_REAL, true,
0, $3);
$$ = tmp;
}
@ -1783,7 +1785,7 @@ tf_port_declaration /* IEEE1800-2005: A.2.7 */
tf_port_item /* IEEE1800-2005: A.2.7 */
: port_direction_opt data_type_or_implicit IDENTIFIER range_opt tf_port_item_expr_opt
{ vector<PWire*>*tmp;
{ vector<pform_tf_port_t>*tmp;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
list<perm_string>* ilist = list_from_identifier($3);
@ -1825,8 +1827,8 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
delete $4;
}
if ($5) {
yyerror(@5, "sorry: Port default expressions not supported yet.");
delete $5;
assert(tmp->size()==1);
tmp->front().defe = $5;
}
}
@ -1849,7 +1851,7 @@ tf_port_item_expr_opt
tf_port_list /* IEEE1800-2005: A.2.7 */
: tf_port_list ',' tf_port_item
{ vector<PWire*>*tmp;
{ vector<pform_tf_port_t>*tmp;
if ($1 && $3) {
size_t s1 = $1->size();
tmp = $1;
@ -3353,7 +3355,7 @@ function_item_list
| function_item_list function_item
{ /* */
if ($1 && $2) {
vector<PWire*>*tmp = $1;
vector<pform_tf_port_t>*tmp = $1;
size_t s1 = tmp->size();
tmp->resize(s1 + $2->size());
for (size_t idx = 0 ; idx < $2->size() ; idx += 1)
@ -5931,13 +5933,13 @@ analog_statement
/* Task items are, other than the statement, task port items and
other block items. */
task_item
: block_item_decl { $$ = new vector<PWire*>(0); }
: block_item_decl { $$ = new vector<pform_tf_port_t>(0); }
| tf_port_declaration { $$ = $1; }
;
task_item_list
: task_item_list task_item
{ vector<PWire*>*tmp = $1;
{ vector<pform_tf_port_t>*tmp = $1;
size_t s1 = tmp->size();
tmp->resize(s1 + $2->size());
for (size_t idx = 0 ; idx < $2->size() ; idx += 1)

View File

@ -2412,7 +2412,7 @@ void pform_makewire(const struct vlltype&li,
* constraints as those of tasks, so this works fine. Functions have
* no output or inout ports.
*/
vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
ivl_variable_type_t vtype,
bool signed_flag,
@ -2422,7 +2422,7 @@ vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
{
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
assert(names);
vector<PWire*>*res = new vector<PWire*>(0);
vector<pform_tf_port_t>*res = new vector<pform_tf_port_t>(0);
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
@ -2447,7 +2447,7 @@ vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
curw->set_range(*range, SR_PORT);
}
res->push_back(curw);
res->push_back(pform_tf_port_t(curw));
}
delete range;
@ -2455,7 +2455,7 @@ vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
return res;
}
static vector<PWire*>*do_make_task_ports(const struct vlltype&loc,
static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
ivl_variable_type_t var_type,
data_type_t*data_type,
@ -2463,7 +2463,7 @@ static vector<PWire*>*do_make_task_ports(const struct vlltype&loc,
{
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
assert(names);
vector<PWire*>*res = new vector<PWire*>(0);
vector<pform_tf_port_t>*res = new vector<pform_tf_port_t>(0);
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++cur) {
@ -2478,13 +2478,13 @@ static vector<PWire*>*do_make_task_ports(const struct vlltype&loc,
pform_put_wire_in_scope(name, curw);
}
res->push_back(curw);
res->push_back(pform_tf_port_t(curw));
}
delete names;
return res;
}
vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
data_type_t*vtype,
list<perm_string>*names)

View File

@ -442,7 +442,7 @@ extern void pform_make_pgassign_list(list<PExpr*>*alist,
/* Given a port type and a list of names, make a list of wires that
can be used as task port information. */
extern std::vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
extern std::vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
ivl_variable_type_t vtype,
bool signed_flag,
@ -450,7 +450,7 @@ extern std::vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
list<perm_string>*names,
bool isint = false);
extern std::vector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
extern std::vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
data_type_t*vtype,
list<perm_string>*names);

View File

@ -984,13 +984,13 @@ void PTaskFunc::dump_ports_(std::ostream&out, unsigned ind) const
return;
for (unsigned idx = 0 ; idx < ports_->size() ; idx += 1) {
if (ports_->at(idx) == 0) {
if (ports_->at(idx).port == 0) {
out << setw(ind) << "" << "ERROR PORT" << endl;
continue;
}
out << setw(ind) << "";
switch (ports_->at(idx)->get_port_type()) {
switch (ports_->at(idx).port->get_port_type()) {
case NetNet::PINPUT:
out << "input ";
break;
@ -1010,7 +1010,11 @@ void PTaskFunc::dump_ports_(std::ostream&out, unsigned ind) const
assert(0);
break;
}
out << ports_->at(idx)->basename() << ";" << endl;
out << ports_->at(idx).port->basename();
if (ports_->at(idx).defe) {
out << " = " << *ports_->at(idx).defe;
}
out << ";" << endl;
}
}

View File

@ -79,13 +79,15 @@ void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net)
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,
vector<pform_tf_port_t>*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);
assert(this_port->at(0).defe == 0);
PWire*this_wire = this_port->at(0).port;
delete this_port;
net->set_this(pform_cur_class->type, this_wire);

View File

@ -39,6 +39,7 @@
class Design;
class NetScope;
class PExpr;
class PWire;
class Statement;
class ivl_type_s;
typedef named<verinum> named_number_t;
@ -70,6 +71,14 @@ struct decl_assignment_t {
std::auto_ptr<PExpr> expr;
};
struct pform_tf_port_t {
PWire*port;
PExpr*defe;
inline pform_tf_port_t() : port(0), defe(0) { }
inline explicit pform_tf_port_t(PWire*p) : port(p), defe(0) { }
};
/*
* This is the base class for data types that are matched by the
* "data_type" rule in the parse rule. We make the type virtual so