Parse support for struct variables.
This commit is contained in:
parent
5677efdfe6
commit
d362c8dba0
|
|
@ -107,10 +107,10 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||||
elab_scope.o elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
|
elab_scope.o elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.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 net_analog.o net_assign.o net_design.o \
|
load_module.o netlist.o netmisc.o net_analog.o net_assign.o net_design.o \
|
||||||
netenum.o net_event.o net_expr.o net_func.o net_link.o net_modulo.o \
|
netenum.o netstruct.o net_event.o net_expr.o net_func.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 \
|
||||||
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
|
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
|
||||||
pform_disciplines.o pform_dump.o pform_types.o \
|
pform_disciplines.o pform_dump.o pform_struct_type.o pform_types.o \
|
||||||
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
|
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
|
||||||
Attrib.o HName.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \
|
Attrib.o HName.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \
|
||||||
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
|
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
|
||||||
|
|
|
||||||
11
PWire.cc
11
PWire.cc
|
|
@ -30,7 +30,8 @@ PWire::PWire(perm_string n,
|
||||||
signed_(false), isint_(false),
|
signed_(false), isint_(false),
|
||||||
port_msb_(0), port_lsb_(0), port_set_(false),
|
port_msb_(0), port_lsb_(0), port_set_(false),
|
||||||
net_msb_(0), net_lsb_(0), net_set_(false), is_scalar_(false),
|
net_msb_(0), net_lsb_(0), net_set_(false), is_scalar_(false),
|
||||||
error_cnt_(0), lidx_(0), ridx_(0), enum_type_(0), discipline_(0)
|
error_cnt_(0), lidx_(0), ridx_(0), enum_type_(0), struct_type_(0),
|
||||||
|
discipline_(0)
|
||||||
{
|
{
|
||||||
if (t == NetNet::INTEGER) {
|
if (t == NetNet::INTEGER) {
|
||||||
type_ = NetNet::REG;
|
type_ = NetNet::REG;
|
||||||
|
|
@ -217,9 +218,17 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||||
void PWire::set_enumeration(enum_type_t*enum_type)
|
void PWire::set_enumeration(enum_type_t*enum_type)
|
||||||
{
|
{
|
||||||
assert(enum_type_ == 0);
|
assert(enum_type_ == 0);
|
||||||
|
assert(struct_type_ == 0);
|
||||||
enum_type_ = enum_type;
|
enum_type_ = enum_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PWire::set_struct_type(struct_type_t*type)
|
||||||
|
{
|
||||||
|
assert(enum_type_ == 0);
|
||||||
|
assert(struct_type_ == 0);
|
||||||
|
struct_type_ = type;
|
||||||
|
}
|
||||||
|
|
||||||
void PWire::set_discipline(ivl_discipline_t d)
|
void PWire::set_discipline(ivl_discipline_t d)
|
||||||
{
|
{
|
||||||
assert(discipline_ == 0);
|
assert(discipline_ == 0);
|
||||||
|
|
|
||||||
2
PWire.h
2
PWire.h
|
|
@ -80,6 +80,7 @@ class PWire : public LineInfo {
|
||||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||||
|
|
||||||
void set_enumeration(enum_type_t*enum_type);
|
void set_enumeration(enum_type_t*enum_type);
|
||||||
|
void set_struct_type(struct_type_t*type);
|
||||||
|
|
||||||
void set_discipline(ivl_discipline_t);
|
void set_discipline(ivl_discipline_t);
|
||||||
ivl_discipline_t get_discipline(void) const;
|
ivl_discipline_t get_discipline(void) const;
|
||||||
|
|
@ -116,6 +117,7 @@ class PWire : public LineInfo {
|
||||||
PExpr*ridx_;
|
PExpr*ridx_;
|
||||||
|
|
||||||
enum_type_t*enum_type_;
|
enum_type_t*enum_type_;
|
||||||
|
struct_type_t*struct_type_;
|
||||||
|
|
||||||
ivl_discipline_t discipline_;
|
ivl_discipline_t discipline_;
|
||||||
|
|
||||||
|
|
|
||||||
28
elab_expr.cc
28
elab_expr.cc
|
|
@ -1418,6 +1418,15 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
||||||
return sys_expr;
|
return sys_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||||
|
Design*des, NetScope*scope,
|
||||||
|
NetNet*net, perm_string method_name)
|
||||||
|
{
|
||||||
|
cerr << li->get_fileline() << ": sorry: structures not supported here." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid, unsigned flags) const
|
unsigned expr_wid, unsigned flags) const
|
||||||
{
|
{
|
||||||
|
|
@ -1456,8 +1465,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
// enumeration? If so then check to see if this is an
|
// enumeration? If so then check to see if this is an
|
||||||
// enumeration method call.
|
// enumeration method call.
|
||||||
if (net != 0) {
|
if (net != 0) {
|
||||||
netenum_t*netenum = net->enumeration();
|
if (netenum_t*netenum = net->enumeration()) {
|
||||||
if (netenum) {
|
|
||||||
// We may need the net expression for the
|
// We may need the net expression for the
|
||||||
// enumeration variable so get it.
|
// enumeration variable so get it.
|
||||||
NetESignal*expr = new NetESignal(net);
|
NetESignal*expr = new NetESignal(net);
|
||||||
|
|
@ -1472,6 +1480,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
expr_wid, tmp,
|
expr_wid, tmp,
|
||||||
parms_.size());
|
parms_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2289,8 +2298,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
// enumeration? If so then check to see if this is an
|
// enumeration? If so then check to see if this is an
|
||||||
// enumeration method call.
|
// enumeration method call.
|
||||||
if (net != 0) {
|
if (net != 0) {
|
||||||
netenum_t*netenum = net->enumeration();
|
// If this net is actually an enum, the method may
|
||||||
if (netenum) {
|
// be an enumeration method.
|
||||||
|
if (netenum_t*netenum = net->enumeration()) {
|
||||||
// We may need the net expression for the
|
// We may need the net expression for the
|
||||||
// enumeration variable so get it.
|
// enumeration variable so get it.
|
||||||
NetESignal*expr = new NetESignal(net);
|
NetESignal*expr = new NetESignal(net);
|
||||||
|
|
@ -2303,6 +2313,16 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
use_path, method_name,
|
use_path, method_name,
|
||||||
expr, expr_wid, NULL, 0);
|
expr, expr_wid, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this net is a struct, the method name may be
|
||||||
|
// a struct member.
|
||||||
|
if (net->struct_type() != 0) {
|
||||||
|
ivl_assert(*this, use_path.back().index.empty());
|
||||||
|
|
||||||
|
return check_for_struct_members(this, des, scope,
|
||||||
|
net, method_name);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
# include "compiler.h"
|
# include "compiler.h"
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "netmisc.h"
|
# include "netmisc.h"
|
||||||
|
# include "netstruct.h"
|
||||||
# include "util.h"
|
# include "util.h"
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
|
|
@ -1094,6 +1095,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
sig->set_enumeration(use_enum);
|
sig->set_enumeration(use_enum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (struct_type_) {
|
||||||
|
netstruct_t*use_type = new netstruct_t;
|
||||||
|
sig->set_struct_type(use_type);
|
||||||
|
}
|
||||||
|
|
||||||
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
|
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
|
||||||
|
|
||||||
ivl_variable_type_t use_data_type = data_type_;
|
ivl_variable_type_t use_data_type = data_type_;
|
||||||
|
|
|
||||||
21
netlist.cc
21
netlist.cc
|
|
@ -450,7 +450,8 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||||
: NetObj(s, n, 1),
|
: NetObj(s, n, 1),
|
||||||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||||
signed_(false), isint_(false), is_scalar_(false), local_flag_(false),
|
signed_(false), isint_(false), is_scalar_(false), local_flag_(false),
|
||||||
enumeration_(0), discipline_(0), msb_(npins-1), lsb_(0), dimensions_(0),
|
enumeration_(0), struct_type_(0), discipline_(0),
|
||||||
|
msb_(npins-1), lsb_(0), dimensions_(0),
|
||||||
s0_(0), e0_(0), eref_count_(0), lref_count_(0)
|
s0_(0), e0_(0), eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
@ -496,7 +497,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
: NetObj(s, n, 1), type_(t),
|
: NetObj(s, n, 1), type_(t),
|
||||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||||
isint_(false), is_scalar_(false), local_flag_(false),
|
isint_(false), is_scalar_(false), local_flag_(false),
|
||||||
enumeration_(0), discipline_(0),
|
enumeration_(0), struct_type_(0), discipline_(0),
|
||||||
msb_(ms), lsb_(ls),
|
msb_(ms), lsb_(ls),
|
||||||
dimensions_(0), s0_(0), e0_(0),
|
dimensions_(0), s0_(0), e0_(0),
|
||||||
eref_count_(0), lref_count_(0)
|
eref_count_(0), lref_count_(0)
|
||||||
|
|
@ -544,7 +545,8 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||||
type_(t), port_type_(NOT_A_PORT),
|
type_(t), port_type_(NOT_A_PORT),
|
||||||
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
||||||
is_scalar_(false), local_flag_(false), enumeration_(0), discipline_(0),
|
is_scalar_(false), local_flag_(false), enumeration_(0), struct_type_(0),
|
||||||
|
discipline_(0),
|
||||||
msb_(ms), lsb_(ls),
|
msb_(ms), lsb_(ls),
|
||||||
dimensions_(1), s0_(array_s), e0_(array_e),
|
dimensions_(1), s0_(array_s), e0_(array_e),
|
||||||
eref_count_(0), lref_count_(0)
|
eref_count_(0), lref_count_(0)
|
||||||
|
|
@ -692,10 +694,23 @@ netenum_t*NetNet::enumeration(void) const
|
||||||
|
|
||||||
void NetNet::set_enumeration(netenum_t*es)
|
void NetNet::set_enumeration(netenum_t*es)
|
||||||
{
|
{
|
||||||
|
ivl_assert(*this, struct_type_ == 0);
|
||||||
ivl_assert(*this, enumeration_ == 0);
|
ivl_assert(*this, enumeration_ == 0);
|
||||||
enumeration_ = es;
|
enumeration_ = es;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
netstruct_t*NetNet::struct_type(void) const
|
||||||
|
{
|
||||||
|
return struct_type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetNet::set_struct_type(netstruct_t*type)
|
||||||
|
{
|
||||||
|
ivl_assert(*this, struct_type_ == 0);
|
||||||
|
ivl_assert(*this, enumeration_ == 0);
|
||||||
|
struct_type_ = type;
|
||||||
|
}
|
||||||
|
|
||||||
ivl_discipline_t NetNet::get_discipline() const
|
ivl_discipline_t NetNet::get_discipline() const
|
||||||
{
|
{
|
||||||
return discipline_;
|
return discipline_;
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ class NetEvWait;
|
||||||
class PExpr;
|
class PExpr;
|
||||||
class PFunction;
|
class PFunction;
|
||||||
class netenum_t;
|
class netenum_t;
|
||||||
|
class netstruct_t;
|
||||||
|
|
||||||
struct target;
|
struct target;
|
||||||
struct functor_t;
|
struct functor_t;
|
||||||
|
|
@ -603,6 +604,9 @@ class NetNet : public NetObj {
|
||||||
void set_enumeration(netenum_t*enum_set);
|
void set_enumeration(netenum_t*enum_set);
|
||||||
netenum_t*enumeration(void) const;
|
netenum_t*enumeration(void) const;
|
||||||
|
|
||||||
|
void set_struct_type(netstruct_t*type);
|
||||||
|
netstruct_t*struct_type(void) const;
|
||||||
|
|
||||||
/* Attach a discipline to the net. */
|
/* Attach a discipline to the net. */
|
||||||
ivl_discipline_t get_discipline() const;
|
ivl_discipline_t get_discipline() const;
|
||||||
void set_discipline(ivl_discipline_t dis);
|
void set_discipline(ivl_discipline_t dis);
|
||||||
|
|
@ -676,6 +680,7 @@ class NetNet : public NetObj {
|
||||||
bool is_scalar_ : 1;
|
bool is_scalar_ : 1;
|
||||||
bool local_flag_: 1;
|
bool local_flag_: 1;
|
||||||
netenum_t*enumeration_;
|
netenum_t*enumeration_;
|
||||||
|
netstruct_t*struct_type_;
|
||||||
ivl_discipline_t discipline_;
|
ivl_discipline_t discipline_;
|
||||||
|
|
||||||
long msb_, lsb_;
|
long msb_, lsb_;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "netstruct.h"
|
||||||
|
|
||||||
|
netstruct_t::netstruct_t()
|
||||||
|
: packed_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
netstruct_t::~netstruct_t()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef __netstruct_H
|
||||||
|
#define __netstruct_H
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "LineInfo.h"
|
||||||
|
|
||||||
|
class netstruct_t : public LineInfo {
|
||||||
|
|
||||||
|
public:
|
||||||
|
netstruct_t();
|
||||||
|
~netstruct_t();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool packed_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
135
parse.y
135
parse.y
|
|
@ -330,6 +330,13 @@ static void current_task_set_statement(vector<Statement*>*s)
|
||||||
net_decl_assign_t*net_decl_assign;
|
net_decl_assign_t*net_decl_assign;
|
||||||
enum_type_t*enum_type;
|
enum_type_t*enum_type;
|
||||||
|
|
||||||
|
decl_assignment_t*decl_assignment;
|
||||||
|
list<decl_assignment_t*>*decl_assignments;
|
||||||
|
|
||||||
|
struct_member_t*struct_member;
|
||||||
|
list<struct_member_t*>*struct_members;
|
||||||
|
struct_type_t*struct_type;
|
||||||
|
|
||||||
verinum* number;
|
verinum* number;
|
||||||
|
|
||||||
verireal* realtime;
|
verireal* realtime;
|
||||||
|
|
@ -436,7 +443,8 @@ static void current_task_set_statement(vector<Statement*>*s)
|
||||||
|
|
||||||
%type <flag> from_exclude
|
%type <flag> from_exclude
|
||||||
%type <number> number pos_neg_number
|
%type <number> number pos_neg_number
|
||||||
%type <flag> unsigned_signed_opt signed_unsigned_opt reg_opt
|
%type <flag> unsigned_signed_opt signed_unsigned_opt
|
||||||
|
%type <flag> K_packed_opt K_reg_opt
|
||||||
%type <flag> udp_reg_opt edge_operator automatic_opt
|
%type <flag> udp_reg_opt edge_operator automatic_opt
|
||||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||||
%type <letter> udp_input_sym udp_output_sym
|
%type <letter> udp_input_sym udp_output_sym
|
||||||
|
|
@ -491,6 +499,13 @@ static void current_task_set_statement(vector<Statement*>*s)
|
||||||
%type <exprs> expression_list_with_nuls expression_list_proper
|
%type <exprs> expression_list_with_nuls expression_list_proper
|
||||||
%type <exprs> cont_assign cont_assign_list
|
%type <exprs> cont_assign cont_assign_list
|
||||||
|
|
||||||
|
%type <decl_assignment> variable_decl_assignment
|
||||||
|
%type <decl_assignments> list_of_variable_decl_assignments
|
||||||
|
|
||||||
|
%type <struct_member> struct_union_member
|
||||||
|
%type <struct_members> struct_union_member_list
|
||||||
|
%type <struct_type> struct_data_type
|
||||||
|
|
||||||
%type <exprs> range range_opt
|
%type <exprs> range range_opt
|
||||||
%type <dimensions> dimensions_opt dimensions
|
%type <dimensions> dimensions_opt dimensions
|
||||||
%type <nettype> net_type var_type net_type_opt
|
%type <nettype> net_type var_type net_type_opt
|
||||||
|
|
@ -695,6 +710,13 @@ block_item_decl
|
||||||
if ($1) delete $1;
|
if ($1) delete $1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* struct data type declarations */
|
||||||
|
|
||||||
|
| attribute_list_opt struct_data_type register_variable_list ';'
|
||||||
|
{ pform_set_struct_type($2, $3);
|
||||||
|
if ($1) delete $1;
|
||||||
|
}
|
||||||
|
|
||||||
/* real declarations are fairly simple as there is no range of
|
/* real declarations are fairly simple as there is no range of
|
||||||
signed flag in the declaration. Create the real as a NetNet::REG
|
signed flag in the declaration. Create the real as a NetNet::REG
|
||||||
with real value. Note that real and realtime are interchangeable
|
with real value. Note that real and realtime are interchangeable
|
||||||
|
|
@ -879,6 +901,63 @@ enum_name
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
struct_data_type
|
||||||
|
: K_struct K_packed_opt '{' struct_union_member_list '}'
|
||||||
|
{ struct_type_t*tmp = new struct_type_t;
|
||||||
|
FILE_NAME(tmp, @1);
|
||||||
|
tmp->packed_flag = $2;
|
||||||
|
tmp->members .reset($4);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| K_struct K_packed_opt '{' error '}'
|
||||||
|
{ yyerror(@4, "error: Errors in struct/union member list.");
|
||||||
|
yyerrok;
|
||||||
|
struct_type_t*tmp = new struct_type_t;
|
||||||
|
FILE_NAME(tmp, @1);
|
||||||
|
tmp->packed_flag = $2;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_union_member_list
|
||||||
|
: struct_union_member_list struct_union_member
|
||||||
|
{ list<struct_member_t*>*tmp = $1;
|
||||||
|
tmp->push_back($2);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| struct_union_member
|
||||||
|
{ list<struct_member_t*>*tmp = new list<struct_member_t*>;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_union_member
|
||||||
|
: attribute_list_opt K_bit range_opt list_of_variable_decl_assignments ';'
|
||||||
|
{ struct_member_t*tmp = new struct_member_t;
|
||||||
|
FILE_NAME(tmp, @2);
|
||||||
|
tmp->type = IVL_VT_BOOL;
|
||||||
|
tmp->range .reset($3);
|
||||||
|
tmp->names .reset($4);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| attribute_list_opt K_logic range_opt list_of_variable_decl_assignments ';'
|
||||||
|
{ struct_member_t*tmp = new struct_member_t;
|
||||||
|
FILE_NAME(tmp, @2);
|
||||||
|
tmp->type = IVL_VT_LOGIC;
|
||||||
|
tmp->range .reset($3);
|
||||||
|
tmp->names .reset($4);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| attribute_list_opt atom2_type list_of_variable_decl_assignments ';'
|
||||||
|
{ struct_member_t*tmp = new struct_member_t;
|
||||||
|
FILE_NAME(tmp, @2);
|
||||||
|
tmp->type = IVL_VT_BOOL;
|
||||||
|
tmp->range .reset( make_range_from_width($2) );
|
||||||
|
tmp->names .reset($3);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
case_item
|
case_item
|
||||||
: expression_list_proper ':' statement_or_null
|
: expression_list_proper ':' statement_or_null
|
||||||
{ PCase::Item*tmp = new PCase::Item;
|
{ PCase::Item*tmp = new PCase::Item;
|
||||||
|
|
@ -3954,6 +4033,40 @@ register_variable_list
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* TODO: Replace register_variable_list with list_of_variable_decl_assignments. */
|
||||||
|
list_of_variable_decl_assignments
|
||||||
|
: variable_decl_assignment
|
||||||
|
{ list<decl_assignment_t*>*tmp = new list<decl_assignment_t*>;
|
||||||
|
tmp->push_back($1);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| list_of_variable_decl_assignments ',' variable_decl_assignment
|
||||||
|
{ list<decl_assignment_t*>*tmp = $1;
|
||||||
|
tmp->push_back($3);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
variable_decl_assignment
|
||||||
|
: IDENTIFIER dimensions_opt
|
||||||
|
{ decl_assignment_t*tmp = new decl_assignment_t;
|
||||||
|
tmp->name = lex_strings.make($1);
|
||||||
|
if ($2) {
|
||||||
|
tmp->index = *$2;
|
||||||
|
delete $2;
|
||||||
|
}
|
||||||
|
delete[]$1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| IDENTIFIER '=' expression
|
||||||
|
{ decl_assignment_t*tmp = new decl_assignment_t;
|
||||||
|
tmp->name = lex_strings.make($1);
|
||||||
|
tmp->expr .reset($3);
|
||||||
|
delete[]$1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
real_variable
|
real_variable
|
||||||
: IDENTIFIER dimensions_opt
|
: IDENTIFIER dimensions_opt
|
||||||
{ perm_string name = lex_strings.make($1);
|
{ perm_string name = lex_strings.make($1);
|
||||||
|
|
@ -4820,13 +4933,8 @@ task_item
|
||||||
| task_port_item { $$ = $1; }
|
| task_port_item { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
reg_opt
|
|
||||||
: K_reg { $$ = true; }
|
|
||||||
| { $$ = false; }
|
|
||||||
;
|
|
||||||
|
|
||||||
task_port_item
|
task_port_item
|
||||||
: K_input reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
: K_input K_reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||||
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
|
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
|
||||||
$2 ? IVL_VT_LOGIC :
|
$2 ? IVL_VT_LOGIC :
|
||||||
IVL_VT_NO_TYPE,
|
IVL_VT_NO_TYPE,
|
||||||
|
|
@ -4834,7 +4942,7 @@ task_port_item
|
||||||
@1.text, @1.first_line);
|
@1.text, @1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_output reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
| K_output K_reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||||
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
|
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
|
||||||
$2 ? IVL_VT_LOGIC :
|
$2 ? IVL_VT_LOGIC :
|
||||||
IVL_VT_NO_TYPE,
|
IVL_VT_NO_TYPE,
|
||||||
|
|
@ -4842,7 +4950,7 @@ task_port_item
|
||||||
@1.text, @1.first_line);
|
@1.text, @1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_inout reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
| K_inout K_reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||||
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
|
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
|
||||||
$2 ? IVL_VT_LOGIC :
|
$2 ? IVL_VT_LOGIC :
|
||||||
IVL_VT_NO_TYPE,
|
IVL_VT_NO_TYPE,
|
||||||
|
|
@ -4954,7 +5062,7 @@ task_item_list_opt
|
||||||
|
|
||||||
task_port_decl
|
task_port_decl
|
||||||
|
|
||||||
: K_input reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
: K_input K_reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||||
{ port_declaration_context.port_type = NetNet::PINPUT;
|
{ port_declaration_context.port_type = NetNet::PINPUT;
|
||||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
port_declaration_context.sign_flag = $3;
|
port_declaration_context.sign_flag = $3;
|
||||||
|
|
@ -4968,7 +5076,7 @@ task_port_decl
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_output reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
| K_output K_reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||||
{ port_declaration_context.port_type = NetNet::POUTPUT;
|
{ port_declaration_context.port_type = NetNet::POUTPUT;
|
||||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
port_declaration_context.sign_flag = $3;
|
port_declaration_context.sign_flag = $3;
|
||||||
|
|
@ -4981,7 +5089,7 @@ task_port_decl
|
||||||
@1.text, @1.first_line);
|
@1.text, @1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_inout reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
| K_inout K_reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||||
{ port_declaration_context.port_type = NetNet::PINOUT;
|
{ port_declaration_context.port_type = NetNet::PINOUT;
|
||||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
port_declaration_context.sign_flag = $3;
|
port_declaration_context.sign_flag = $3;
|
||||||
|
|
@ -5504,3 +5612,6 @@ udp_primitive
|
||||||
delete[]$6;
|
delete[]$6;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
||||||
|
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
||||||
|
|
|
||||||
2
pform.cc
2
pform.cc
|
|
@ -385,7 +385,7 @@ static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
|
||||||
lexical_scope->enum_sets.push_back(enum_set);
|
lexical_scope->enum_sets.push_back(enum_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type)
|
PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type)
|
||||||
{
|
{
|
||||||
PWire*cur = pform_get_wire_in_scope(name);
|
PWire*cur = pform_get_wire_in_scope(name);
|
||||||
if (cur == 0) {
|
if (cur == 0) {
|
||||||
|
|
|
||||||
4
pform.h
4
pform.h
|
|
@ -135,6 +135,8 @@ extern void pform_set_default_nettype(NetNet::Type net,
|
||||||
*/
|
*/
|
||||||
extern PWire* pform_get_wire_in_scope(perm_string name);
|
extern PWire* pform_get_wire_in_scope(perm_string name);
|
||||||
|
|
||||||
|
extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The parser uses startmodule and endmodule together to build up a
|
* The parser uses startmodule and endmodule together to build up a
|
||||||
* module as it parses it. The startmodule tells the pform code that a
|
* module as it parses it. The startmodule tells the pform code that a
|
||||||
|
|
@ -280,6 +282,8 @@ extern void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_
|
||||||
|
|
||||||
extern void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names);
|
extern void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names);
|
||||||
|
|
||||||
|
extern void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names);
|
||||||
|
|
||||||
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
||||||
$attribute syntax, which can only set string values to
|
$attribute syntax, which can only set string values to
|
||||||
attributes. The functions keep the value strings that are
|
attributes. The functions keep the value strings that are
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "pform.h"
|
||||||
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we parse a packed struct, we can early on (right here) figure
|
||||||
|
* out the base type of the packed variable. Elaboration, later on,
|
||||||
|
* well figure out the rest.
|
||||||
|
*/
|
||||||
|
static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name)
|
||||||
|
{
|
||||||
|
ivl_variable_type_t base_type = IVL_VT_BOOL;
|
||||||
|
|
||||||
|
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
|
||||||
|
; cur != struct_type->members->end() ; ++ cur) {
|
||||||
|
|
||||||
|
struct_member_t*tmp = *cur;
|
||||||
|
|
||||||
|
if (tmp->type == IVL_VT_BOOL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp->type == IVL_VT_LOGIC) {
|
||||||
|
base_type = IVL_VT_LOGIC;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PWire*net = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, base_type);
|
||||||
|
net->set_struct_type(struct_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pform_set_struct_type(struct_type_t*struct_type, perm_string name)
|
||||||
|
{
|
||||||
|
if (struct_type->packed_flag) {
|
||||||
|
pform_set_packed_struct(struct_type, name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, can only handle packed structs.
|
||||||
|
ivl_assert(*struct_type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names)
|
||||||
|
{
|
||||||
|
for (list<perm_string>::iterator cur = names->begin()
|
||||||
|
; cur != names->end() ; ++ cur) {
|
||||||
|
pform_set_struct_type(struct_type, *cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -57,6 +57,12 @@ struct name_component_t {
|
||||||
std::list<index_component_t>index;
|
std::list<index_component_t>index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct decl_assignment_t {
|
||||||
|
perm_string name;
|
||||||
|
std::list<index_component_t>index;
|
||||||
|
std::auto_ptr<PExpr> expr;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The enum_type_t holds the parsed declaration to represent an
|
* The enum_type_t holds the parsed declaration to represent an
|
||||||
* enumeration. Since this is in the pform, it represents the type
|
* enumeration. Since this is in the pform, it represents the type
|
||||||
|
|
@ -71,6 +77,16 @@ struct enum_type_t {
|
||||||
LineInfo li;
|
LineInfo li;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct struct_member_t : public LineInfo {
|
||||||
|
ivl_variable_type_t type;
|
||||||
|
std::auto_ptr< list<PExpr*> > range;
|
||||||
|
std::auto_ptr< list<decl_assignment_t*> > names;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct struct_type_t : public LineInfo {
|
||||||
|
bool packed_flag;
|
||||||
|
std::auto_ptr< list<struct_member_t*> > members;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The pform_name_t is the general form for a hierarchical
|
* The pform_name_t is the general form for a hierarchical
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue