Handle queue types and expressions at pform level.
This commit is contained in:
parent
4ea512c4fd
commit
6d052d4ff7
|
|
@ -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 \
|
||||||
|
|
|
||||||
5
PExpr.h
5
PExpr.h
|
|
@ -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,
|
||||||
|
|
|
||||||
39
elab_expr.cc
39
elab_expr.cc
|
|
@ -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.
|
||||||
|
|
|
||||||
27
elab_sig.cc
27
elab_sig.cc
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
@ -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
20
parse.y
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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() { }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue