Handle task/function default expressions in parsing/pform.
This gets it to (but not through) the elaborator.
This commit is contained in:
parent
d8f945be23
commit
9a116498a2
6
PTask.cc
6
PTask.cc
|
|
@ -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__)
|
||||
|
|
|
|||
4
PTask.h
4
PTask.h
|
|
@ -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_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
30
parse.y
|
|
@ -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)
|
||||
|
|
|
|||
14
pform.cc
14
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<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)
|
||||
|
|
|
|||
4
pform.h
4
pform.h
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue