Handle queue types and expressions at pform level.

This commit is contained in:
Stephen Williams 2014-07-29 20:41:03 -07:00
parent 4ea512c4fd
commit 6d052d4ff7
9 changed files with 195 additions and 14 deletions

View File

@ -109,7 +109,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \ load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
net_design.o netclass.o netdarray.o \ net_design.o netclass.o netdarray.o \
netenum.o netparray.o netscalar.o netstruct.o netvector.o \ netenum.o netparray.o netqueue.o netscalar.o netstruct.o netvector.o \
net_event.o net_expr.o net_func.o \ net_event.o net_expr.o net_func.o \
net_func_eval.o net_link.o net_modulo.o \ net_func_eval.o net_link.o net_modulo.o \
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \

View File

@ -505,6 +505,11 @@ class PEIdent : public PExpr {
NetESignal*net, NetESignal*net,
NetScope*found, NetScope*found,
bool need_const) const; bool need_const) const;
NetExpr*elaborate_expr_net_bit_last_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_class_member_(Design*des, NetExpr*elaborate_expr_class_member_(Design*des,
NetScope*scope, NetScope*scope,

View File

@ -1749,6 +1749,14 @@ static const netstruct_t::member_t*get_struct_member(const LineInfo*li,
bool calculate_part(const LineInfo*li, Design*des, NetScope*scope, bool calculate_part(const LineInfo*li, Design*des, NetScope*scope,
const index_component_t&index, long&off, unsigned long&wid) const index_component_t&index, long&off, unsigned long&wid)
{ {
if (index.sel == index_component_t::SEL_BIT_LAST) {
cerr << li->get_fileline() << ": sorry: "
<< "Last element select expression "
<< "not supported." << endl;
des->errors += 1;
return false;
}
// Evaluate the last index expression into a constant long. // Evaluate the last index expression into a constant long.
NetExpr*texpr = elab_and_eval(des, scope, index.msb, -1, true); NetExpr*texpr = elab_and_eval(des, scope, index.msb, -1, true);
long msb; long msb;
@ -2839,21 +2847,31 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
if ((net == 0) || (net->packed_dimensions() <= 1)) if ((net == 0) || (net->packed_dimensions() <= 1))
use_width = 1; use_width = 1;
break; break;
case index_component_t::SEL_BIT_LAST:
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::test_width: "
<< "Queue/Darray last index ($)" << endl;
}
break;
default: default:
ivl_assert(*this, 0); ivl_assert(*this, 0);
} }
if (const netdarray_t*darray = net? net->darray_type() : 0) { if (const netdarray_t*darray = net? net->darray_type() : 0) {
if (use_sel == index_component_t::SEL_BIT) { switch (use_sel) {
case index_component_t::SEL_BIT:
case index_component_t::SEL_BIT_LAST:
expr_type_ = darray->element_base_type(); expr_type_ = darray->element_base_type();
expr_width_ = darray->element_width(); expr_width_ = darray->element_width();
min_width_ = expr_width_; min_width_ = expr_width_;
signed_flag_ = net->get_signed(); signed_flag_ = net->get_signed();
} else { break;
default:
expr_type_ = net->data_type(); expr_type_ = net->data_type();
expr_width_ = net->vector_width(); expr_width_ = net->vector_width();
min_width_ = expr_width_; min_width_ = expr_width_;
signed_flag_ = net->get_signed(); signed_flag_ = net->get_signed();
break;
} }
return expr_width_; return expr_width_;
} }
@ -3917,6 +3935,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
return 0; return 0;
} }
ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST);
if (use_sel == index_component_t::SEL_BIT) if (use_sel == index_component_t::SEL_BIT)
return elaborate_expr_param_bit_(des, scope, par, found_in, return elaborate_expr_param_bit_(des, scope, par, found_in,
par_msb, par_lsb, need_const); par_msb, par_lsb, need_const);
@ -4645,6 +4665,17 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
return ss; return ss;
} }
NetExpr* PEIdent::elaborate_expr_net_bit_last_(Design*des, NetScope*scope,
NetESignal*net,
NetScope*found_in,
bool need_const) const
{
cerr << get_fileline() << ": sorry: "
<< "Don't yet know how to elaborate net expresion [$]" << endl;
des->errors += 1;
return 0;
}
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope, NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in, NetNet*net, NetScope*found_in,
unsigned expr_wid, unsigned expr_wid,
@ -4697,6 +4728,10 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
return elaborate_expr_net_bit_(des, scope, node, found_in, return elaborate_expr_net_bit_(des, scope, node, found_in,
need_const); need_const);
if (use_sel == index_component_t::SEL_BIT_LAST)
return elaborate_expr_net_bit_last_(des, scope, node, found_in,
need_const);
// It's not anything else, so this must be a simple identifier // It's not anything else, so this must be a simple identifier
// expression with no part or bit select. Return the signal // expression with no part or bit select. Return the signal
// itself as the expression. // itself as the expression.

View File

@ -41,6 +41,7 @@
# include "netvector.h" # include "netvector.h"
# include "netdarray.h" # include "netdarray.h"
# include "netparray.h" # include "netparray.h"
# include "netqueue.h"
# include "util.h" # include "util.h"
# include "ivl_assert.h" # include "ivl_assert.h"
@ -1084,7 +1085,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
list<netrange_t>unpacked_dimensions; list<netrange_t>unpacked_dimensions;
netdarray_t*netarray = 0; netdarray_t*netdarray = 0;
for (list<pform_range_t>::const_iterator cur = unpacked_.begin() for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
; cur != unpacked_.end() ; ++cur) { ; cur != unpacked_.end() ; ++cur) {
@ -1097,13 +1098,27 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (use_lidx==0 && use_ridx==0) { if (use_lidx==0 && use_ridx==0) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_); netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
packed_dimensions.clear(); packed_dimensions.clear();
ivl_assert(*this, netarray==0); ivl_assert(*this, netdarray==0);
netarray = new netdarray_t(vec); netdarray = new netdarray_t(vec);
continue; continue;
} }
// Special case: Detect the mark for a QUEUE
// declaration, which is the dimensions [null:<nil>].
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
netdarray = new netqueue_t(vec);
continue;
}
cerr << get_fileline() << ": XXXX: "
<< "use_lidx=" << use_lidx
<< ", use_ridx=" << use_ridx << endl;
// Cannot handle dynamic arrays of arrays yet. // Cannot handle dynamic arrays of arrays yet.
ivl_assert(*this, netarray==0); ivl_assert(*this, netdarray==0);
ivl_assert(*this, use_lidx && use_ridx); ivl_assert(*this, use_lidx && use_ridx);
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true); NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
@ -1246,7 +1261,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum); sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
} else if (netarray) { } else if (netdarray) {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype cerr << get_fileline() << ": debug: Create signal " << wtype
@ -1256,7 +1271,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
ivl_assert(*this, packed_dimensions.empty()); ivl_assert(*this, packed_dimensions.empty());
ivl_assert(*this, unpacked_dimensions.empty()); ivl_assert(*this, unpacked_dimensions.empty());
sig = new NetNet(scope, name_, wtype, netarray); sig = new NetNet(scope, name_, wtype, netdarray);
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) { } else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
// The pform gives us a parray_type_t for packed arrays // The pform gives us a parray_type_t for packed arrays

41
netqueue.cc Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "netqueue.h"
# include <iostream>
using namespace std;
netqueue_t::netqueue_t(ivl_type_t vec)
: netdarray_t(vec)
{
}
netqueue_t::~netqueue_t()
{
}
bool netqueue_t::test_compatibility(ivl_type_t that) const
{
const netqueue_t*that_q = dynamic_cast<const netqueue_t*>(that);
if (that_q == 0)
return false;
return element_type()->type_compatible(that_q->element_type());
}

40
netqueue.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef IVL__netqueue_H
#define IVL__netqueue_H
/*
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "netdarray.h"
# include "ivl_target.h"
/*
* A queue type is actually a dynamic array with a few extra
* methods. This will probably result in a different implementation at
* run-time, but for the most part this applies during elaboration.
*/
class netqueue_t : public netdarray_t {
public:
explicit netqueue_t(ivl_type_t vec);
~netqueue_t();
private:
bool test_compatibility(ivl_type_t that) const;
};
#endif

20
parse.y
View File

@ -2041,10 +2041,8 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
| '[' '$' ']' | '[' '$' ']'
{ // SystemVerilog queue { // SystemVerilog queue
list<pform_range_t> *tmp = new list<pform_range_t>; list<pform_range_t> *tmp = new list<pform_range_t>;
pform_range_t index (0,0); pform_range_t index (new PENull,0);
if (gn_system_verilog()) { if (!gn_system_verilog()) {
yyerror("sorry: Dynamic array ranges not supported.");
} else {
yyerror("error: Queue declarations require System Verilog."); yyerror("error: Queue declarations require System Verilog.");
} }
tmp->push_back(index); tmp->push_back(index);
@ -3702,6 +3700,20 @@ hierarchy_identifier
tail.index.push_back(itmp); tail.index.push_back(itmp);
$$ = tmp; $$ = tmp;
} }
| hierarchy_identifier '[' '$' ']'
{ pform_name_t * tmp = $1;
name_component_t&tail = tmp->back();
if (! gn_system_verilog()) {
yyerror(@3, "error: Last element expression ($) "
"requires SystemVerilog. Try enabling SystemVerilog.");
}
index_component_t itmp;
itmp.sel = index_component_t::SEL_BIT_LAST;
itmp.msb = 0;
itmp.lsb = 0;
tail.index.push_back(itmp);
$$ = tmp;
}
| hierarchy_identifier '[' expression ':' expression ']' | hierarchy_identifier '[' expression ':' expression ']'
{ pform_name_t * tmp = $1; { pform_name_t * tmp = $1;
name_component_t&tail = tmp->back(); name_component_t&tail = tmp->back();

View File

@ -62,6 +62,9 @@ ostream& operator<< (ostream&out, const index_component_t&that)
case index_component_t::SEL_BIT: case index_component_t::SEL_BIT:
out << *that.msb; out << *that.msb;
break; break;
case index_component_t::SEL_BIT_LAST:
out << "$";
break;
case index_component_t::SEL_PART: case index_component_t::SEL_PART:
out << *that.msb << ":" << *that.lsb; out << *that.msb << ":" << *that.lsb;
break; break;

View File

@ -46,10 +46,40 @@ class ivl_type_s;
class netenum_t; class netenum_t;
typedef named<verinum> named_number_t; typedef named<verinum> named_number_t;
typedef named<PExpr*> named_pexpr_t; typedef named<PExpr*> named_pexpr_t;
/*
* The pform_range_t holds variable diimensions for type
* declarations. The two expressions are interpreted as the first and
* last values of the range. For example:
*
* [<expr1> : <expr2>] -- Normal array range
* first == <expr1>
* second = <expr2>
*
* [<expr>] -- SystemVerilog canonical range
* first = PENumber(0)
* second = <expr> - 1;
*
* [ ] -- Dynamic array
* first = 0
* second = 0
*
* [ $ ] -- Queue type
* first = PENull
* second = 0
*/
typedef std::pair<PExpr*,PExpr*> pform_range_t; typedef std::pair<PExpr*,PExpr*> pform_range_t;
/*
* Semantic NOTES:
* - The SEL_BIT is a single expression. This might me a bit select
* of a vector, or a word select of an array.
*
* - The SEL_BIT_LAST index component is an array/queue [$] index,
* that is the last item in the variable.
*/
struct index_component_t { struct index_component_t {
enum ctype_t { SEL_NONE, SEL_BIT, SEL_PART, SEL_IDX_UP, SEL_IDX_DO }; enum ctype_t { SEL_NONE, SEL_BIT, SEL_BIT_LAST, SEL_PART, SEL_IDX_UP, SEL_IDX_DO };
index_component_t() : sel(SEL_NONE), msb(0), lsb(0) { }; index_component_t() : sel(SEL_NONE), msb(0), lsb(0) { };
~index_component_t() { } ~index_component_t() { }