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 \
|
||||
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 \
|
||||
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_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 \
|
||||
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 \
|
||||
|
|
|
|||
11
PWire.cc
11
PWire.cc
|
|
@ -30,7 +30,8 @@ PWire::PWire(perm_string n,
|
|||
signed_(false), isint_(false),
|
||||
port_msb_(0), port_lsb_(0), port_set_(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) {
|
||||
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)
|
||||
{
|
||||
assert(enum_type_ == 0);
|
||||
assert(struct_type_ == 0);
|
||||
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)
|
||||
{
|
||||
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_enumeration(enum_type_t*enum_type);
|
||||
void set_struct_type(struct_type_t*type);
|
||||
|
||||
void set_discipline(ivl_discipline_t);
|
||||
ivl_discipline_t get_discipline(void) const;
|
||||
|
|
@ -116,6 +117,7 @@ class PWire : public LineInfo {
|
|||
PExpr*ridx_;
|
||||
|
||||
enum_type_t*enum_type_;
|
||||
struct_type_t*struct_type_;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
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 method call.
|
||||
if (net != 0) {
|
||||
netenum_t*netenum = net->enumeration();
|
||||
if (netenum) {
|
||||
if (netenum_t*netenum = net->enumeration()) {
|
||||
// We may need the net expression for the
|
||||
// enumeration variable so get it.
|
||||
NetESignal*expr = new NetESignal(net);
|
||||
|
|
@ -1472,6 +1480,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
expr_wid, tmp,
|
||||
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 method call.
|
||||
if (net != 0) {
|
||||
netenum_t*netenum = net->enumeration();
|
||||
if (netenum) {
|
||||
// If this net is actually an enum, the method may
|
||||
// be an enumeration method.
|
||||
if (netenum_t*netenum = net->enumeration()) {
|
||||
// We may need the net expression for the
|
||||
// enumeration variable so get it.
|
||||
NetESignal*expr = new NetESignal(net);
|
||||
|
|
@ -2303,6 +2313,16 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
use_path, method_name,
|
||||
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 "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "netstruct.h"
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
|
@ -1094,6 +1095,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
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();
|
||||
|
||||
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),
|
||||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||
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)
|
||||
{
|
||||
assert(s);
|
||||
|
|
@ -496,7 +497,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
|||
: NetObj(s, n, 1), type_(t),
|
||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||
isint_(false), is_scalar_(false), local_flag_(false),
|
||||
enumeration_(0), discipline_(0),
|
||||
enumeration_(0), struct_type_(0), discipline_(0),
|
||||
msb_(ms), lsb_(ls),
|
||||
dimensions_(0), s0_(0), e0_(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)),
|
||||
type_(t), port_type_(NOT_A_PORT),
|
||||
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),
|
||||
dimensions_(1), s0_(array_s), e0_(array_e),
|
||||
eref_count_(0), lref_count_(0)
|
||||
|
|
@ -692,10 +694,23 @@ netenum_t*NetNet::enumeration(void) const
|
|||
|
||||
void NetNet::set_enumeration(netenum_t*es)
|
||||
{
|
||||
ivl_assert(*this, struct_type_ == 0);
|
||||
ivl_assert(*this, enumeration_ == 0);
|
||||
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
|
||||
{
|
||||
return discipline_;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ class NetEvWait;
|
|||
class PExpr;
|
||||
class PFunction;
|
||||
class netenum_t;
|
||||
class netstruct_t;
|
||||
|
||||
struct target;
|
||||
struct functor_t;
|
||||
|
|
@ -603,6 +604,9 @@ class NetNet : public NetObj {
|
|||
void set_enumeration(netenum_t*enum_set);
|
||||
netenum_t*enumeration(void) const;
|
||||
|
||||
void set_struct_type(netstruct_t*type);
|
||||
netstruct_t*struct_type(void) const;
|
||||
|
||||
/* Attach a discipline to the net. */
|
||||
ivl_discipline_t get_discipline() const;
|
||||
void set_discipline(ivl_discipline_t dis);
|
||||
|
|
@ -676,6 +680,7 @@ class NetNet : public NetObj {
|
|||
bool is_scalar_ : 1;
|
||||
bool local_flag_: 1;
|
||||
netenum_t*enumeration_;
|
||||
netstruct_t*struct_type_;
|
||||
ivl_discipline_t discipline_;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
verireal* realtime;
|
||||
|
|
@ -436,7 +443,8 @@ static void current_task_set_statement(vector<Statement*>*s)
|
|||
|
||||
%type <flag> from_exclude
|
||||
%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 <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||
%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> 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 <dimensions> dimensions_opt dimensions
|
||||
%type <nettype> net_type var_type net_type_opt
|
||||
|
|
@ -695,6 +710,13 @@ block_item_decl
|
|||
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
|
||||
signed flag in the declaration. Create the real as a NetNet::REG
|
||||
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
|
||||
: expression_list_proper ':' statement_or_null
|
||||
{ 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
|
||||
: IDENTIFIER dimensions_opt
|
||||
{ perm_string name = lex_strings.make($1);
|
||||
|
|
@ -4820,13 +4933,8 @@ task_item
|
|||
| task_port_item { $$ = $1; }
|
||||
;
|
||||
|
||||
reg_opt
|
||||
: K_reg { $$ = true; }
|
||||
| { $$ = false; }
|
||||
;
|
||||
|
||||
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,
|
||||
$2 ? IVL_VT_LOGIC :
|
||||
IVL_VT_NO_TYPE,
|
||||
|
|
@ -4834,7 +4942,7 @@ task_port_item
|
|||
@1.text, @1.first_line);
|
||||
$$ = 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,
|
||||
$2 ? IVL_VT_LOGIC :
|
||||
IVL_VT_NO_TYPE,
|
||||
|
|
@ -4842,7 +4950,7 @@ task_port_item
|
|||
@1.text, @1.first_line);
|
||||
$$ = 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,
|
||||
$2 ? IVL_VT_LOGIC :
|
||||
IVL_VT_NO_TYPE,
|
||||
|
|
@ -4954,7 +5062,7 @@ task_item_list_opt
|
|||
|
||||
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.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
|
|
@ -4968,7 +5076,7 @@ task_port_decl
|
|||
$$ = 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.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
|
|
@ -4981,7 +5089,7 @@ task_port_decl
|
|||
@1.text, @1.first_line);
|
||||
$$ = 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.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
|
|
@ -5504,3 +5612,6 @@ udp_primitive
|
|||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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_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
|
||||
* 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_struct_type(struct_type_t*struct_type, list<perm_string>*names);
|
||||
|
||||
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
||||
$attribute syntax, which can only set string values to
|
||||
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;
|
||||
};
|
||||
|
||||
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
|
||||
* enumeration. Since this is in the pform, it represents the type
|
||||
|
|
@ -71,6 +77,16 @@ struct enum_type_t {
|
|||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue