diff --git a/PTask.cc b/PTask.cc index d2ca8e717..d8ce68ccc 100644 --- a/PTask.cc +++ b/PTask.cc @@ -30,7 +30,7 @@ PTaskFunc::~PTaskFunc() { } -void PTaskFunc::set_ports(vector*p) +void PTaskFunc::set_ports(vector*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; + ports_ = new vector; 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__) diff --git a/PTask.h b/PTask.h index a79e5f95c..51877f1d5 100644 --- a/PTask.h +++ b/PTask.h @@ -39,7 +39,7 @@ class PTaskFunc : public PScope, public LineInfo { PTaskFunc(perm_string name, LexicalScope*parent); ~PTaskFunc(); - void set_ports(std::vector*p); + void set_ports(std::vector*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*ports_; + std::vector*ports_; }; /* diff --git a/elab_sig.cc b/elab_sig.cc index a4d812566..9596fdf86 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -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) diff --git a/parse.y b/parse.y index 0c8c6918d..d415d5965 100644 --- a/parse.y +++ b/parse.y @@ -339,6 +339,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector list >*port_list; + vector* 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 %type enum_name_list enum_name %type enum_data_type -%type task_item task_item_list task_item_list_opt -%type tf_port_declaration tf_port_item tf_port_list tf_port_list_opt -%type function_item function_item_list function_item_list_opt +%type function_item function_item_list function_item_list_opt +%type task_item task_item_list task_item_list_opt +%type tf_port_declaration tf_port_item tf_port_list tf_port_list_opt %type port_name parameter_value_byname %type 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*tmp = pform_make_task_ports(@1, $1, + { vector*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*range_stub = make_range_from_width(integer_width); - vector*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, true, + vector*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*range_stub = make_range_from_width(64); - vector*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, false, + vector*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*tmp = pform_make_task_ports(@1, $1, IVL_VT_REAL, true, + { vector*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*tmp; + { vector*tmp; NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1; list* 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*tmp; + { vector*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*tmp = $1; + vector*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(0); } + : block_item_decl { $$ = new vector(0); } | tf_port_declaration { $$ = $1; } ; task_item_list : task_item_list task_item - { vector*tmp = $1; + { vector*tmp = $1; size_t s1 = tmp->size(); tmp->resize(s1 + $2->size()); for (size_t idx = 0 ; idx < $2->size() ; idx += 1) diff --git a/pform.cc b/pform.cc index 8d82b96ba..4c595f27b 100644 --- a/pform.cc +++ b/pform.cc @@ -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*pform_make_task_ports(const struct vlltype&loc, +vector*pform_make_task_ports(const struct vlltype&loc, NetNet::PortType pt, ivl_variable_type_t vtype, bool signed_flag, @@ -2422,7 +2422,7 @@ vector*pform_make_task_ports(const struct vlltype&loc, { assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT); assert(names); - vector*res = new vector(0); + vector*res = new vector(0); for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur ) { @@ -2447,7 +2447,7 @@ vector*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*pform_make_task_ports(const struct vlltype&loc, return res; } -static vector*do_make_task_ports(const struct vlltype&loc, +static vector*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*do_make_task_ports(const struct vlltype&loc, { assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT); assert(names); - vector*res = new vector(0); + vector*res = new vector(0); for (list::iterator cur = names->begin() ; cur != names->end() ; ++cur) { @@ -2478,13 +2478,13 @@ static vector*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*pform_make_task_ports(const struct vlltype&loc, +vector*pform_make_task_ports(const struct vlltype&loc, NetNet::PortType pt, data_type_t*vtype, list*names) diff --git a/pform.h b/pform.h index a6f24e439..6eaf170ff 100644 --- a/pform.h +++ b/pform.h @@ -442,7 +442,7 @@ extern void pform_make_pgassign_list(list*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*pform_make_task_ports(const struct vlltype&loc, +extern std::vector*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*pform_make_task_ports(const struct vlltype&loc, list*names, bool isint = false); -extern std::vector*pform_make_task_ports(const struct vlltype&loc, +extern std::vector*pform_make_task_ports(const struct vlltype&loc, NetNet::PortType pt, data_type_t*vtype, list*names); diff --git a/pform_dump.cc b/pform_dump.cc index 5389b6e02..17c01d653 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -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; } } diff --git a/pform_pclass.cc b/pform_pclass.cc index 4899b2366..f82b8120b 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -79,13 +79,15 @@ void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net) list*this_name = new list; this_name->push_back(perm_string::literal("@")); - vector*this_port = pform_make_task_ports(loc, NetNet::PINPUT, + vector*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); diff --git a/pform_types.h b/pform_types.h index 6598f7d26..04fd9ec4a 100644 --- a/pform_types.h +++ b/pform_types.h @@ -39,6 +39,7 @@ class Design; class NetScope; class PExpr; +class PWire; class Statement; class ivl_type_s; typedef named named_number_t; @@ -70,6 +71,14 @@ struct decl_assignment_t { std::auto_ptr 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