'K_MOD_EQ', 'K_AND_EQ', 'K_OR_EQ'),
('right', 'K_XOR_EQ', 'K_LS_EQ', 'K_RS_EQ', 'K_RSS_EQ'),
('right', '?', ':', 'K_inside'),
- ('left', 'K_LOR'),
- ('left', 'K_LAND'),
- ('left', '|'),
- ('left', '^', 'K_NXOR', 'K_NOR'),
- ('left', '&', 'K_NAND'),
- ('left', 'K_EQ', 'K_NE', 'K_CEQ', 'K_CNE', 'K_WEQ', 'K_WNE'),
- ('left', 'K_GE', 'K_LE', '<', '>'),
- ('left', 'K_LS', 'K_RS', 'K_RSS'),
- ('left', '+', '-'),
- ('left', '*', '/', '%'),
- ('left', 'K_POW'),
- ('left', 'UNARY_PREC'),
- ('nonassoc', 'less_than_K_else'),
- ('nonassoc', 'K_else'),
- ('nonassoc', '('),
- ('nonassoc', 'K_exclude'),
- ('nonassoc', 'no_timeunits_declaration'),
- ('nonassoc', 'one_timeunits_declaration'),
+ ('left', 'K_LOR'),
+ ('left', 'K_LAND'),
+ ('left', '|'),
+ ('left', '^', 'K_NXOR', 'K_NOR'),
+ ('left', '&', 'K_NAND'),
+ ('left', 'K_EQ', 'K_NE', 'K_CEQ', 'K_CNE', 'K_WEQ', 'K_WNE'),
+ ('left', 'K_GE', 'K_LE', '<', '>'),
+ ('left', 'K_LS', 'K_RS', 'K_RSS'),
+ ('left', '+', '-'),
+ ('left', '*', '/', '%'),
+ ('left', 'K_POW'),
+ ('left', 'UNARY_PREC'),
+ ('nonassoc', 'less_than_K_else'),
+ ('nonassoc', 'K_else'),
+ ('nonassoc', '('),
+ ('nonassoc', 'K_exclude'),
+ ('nonassoc', 'no_timeunits_declaration'),
+ ('nonassoc', 'one_timeunits_declaration'),
('nonassoc', 'K_timeunit', 'K_timeprecision')
]
IVL_VT_NO_TYPE = 'VT_NO_TYPE'
IVL_VT_BOOL = 'VT_BOOL'
IVL_VT_LOGIC = 'VT_LOGIC'
+"""
+ IVL_VT_VOID = 0, /* Not used */
+ IVL_VT_NO_TYPE = 1, /* Place holder for missing/unknown type. */
+ IVL_VT_REAL = 2,
+ IVL_VT_BOOL = 3,
+ IVL_VT_LOGIC = 4,
+ IVL_VT_STRING = 5,
+ IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */
+ IVL_VT_CLASS = 7, /* SystemVerilog class instances */
+ IVL_VT_QUEUE = 8, /* SystemVerilog queue instances */
+ IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
+"""
NN_NONE = 'NONE'
NN_IMPLICIT = 'IMPLICIT'
NP_PINOUT = 'PINOUT'
NP_PREF = 'PREF'
+def indent(s, i=4):
+ st = ''
+ for x in s:
+ st += str(x)
+ res = []
+ for p in st.split('\n'):
+ res.append(' ' * i + p)
+ return '\n'.join(res)
+
+
+class DataType:
+ def __init__(self, typ, signed):
+ self.typ = typ
+ self.signed = signed
+
+def port_decl(comment, dt, name):
+ if dt.dims is None:
+ width = '' # width: 1
+ else:
+ width = dt.dims
+ # XXX TODO, better checking, should be using data structure... *sigh*
+ width = width[1:-1] # strip brackets
+ width = width.split(':')
+ assert width[0] == '0'
+ width = width[1]
+ return 'self.%s = Signal(%s) # %s' % (name, width, comment)
# -------------- RULES ----------------
()
def p_data_type_1(p):
'''data_type : integer_vector_type unsigned_signed_opt dimensions_opt '''
print('data_type_1', list(p))
+ use_vtype = p[1]
+ reg_flag = False
+ if (use_vtype == IVL_VT_NO_TYPE):
+ use_vtype = IVL_VT_LOGIC
+ reg_flag = True
+ dt = DataType(use_vtype, signed=p[2])
+ dt.dims = p[3]
+ dt.reg_flag = reg_flag
+ p[0] = dt
# { ivl_variable_type_t use_vtype = $1;
# bool reg_flag = false;
# if (use_vtype == IVL_VT_NO_TYPE) {
def p_data_type_2(p):
'''data_type : non_integer_type '''
print('data_type_2', list(p))
+ p[0] = p[1]
# { real_type_t*tmp = new real_type_t($1);
# FILE_NAME(tmp, @1);
# $$ = tmp;
def p_data_type_3(p):
'''data_type : struct_data_type '''
print('data_type_3', list(p))
+ p[0] = p[1]
# { if (!$1->packed_flag) {
# yyerror(@1, "sorry: Unpacked structs not supported.");
# }
print('loop_statement_2', list(p))
# { pform_name_t tmp_hident;
# tmp_hident.push_back(name_component_t(lex_strings.make($4)));
- #
+ #
# PEIdent*tmp_ident = pform_new_ident(tmp_hident);
# FILE_NAME(tmp_ident, @4);
- #
+ #
# PForStatement*tmp_for = new PForStatement(tmp_ident, $6, $8, $10, $13);
# FILE_NAME(tmp_for, @1);
- #
+ #
# pform_pop_scope();
# vector<Statement*>tmp_for_list (1);
# tmp_for_list[0] = tmp_for;
'''loop_statement : K_foreach '(' IDENTIFIER '[' loop_variables ']' ')' _embed1_loop_statement statement_or_null '''
print('loop_statement_7', list(p))
# { PForeach*tmp_for = pform_make_foreach(@1, $3, $5, $9);
- #
+ #
# pform_pop_scope();
# vector<Statement*>tmp_for_list(1);
# tmp_for_list[0] = tmp_for;
# PBlock*tmp = pform_push_block_scope(for_block_name, PBlock::BL_SEQ);
# FILE_NAME(tmp, @1);
# current_block_stack.push(tmp);
- #
+ #
# list<decl_assignment_t*>assign_list;
# decl_assignment_t*tmp_assign = new decl_assignment_t;
# tmp_assign->name = lex_strings.make($4);
# char for_block_name[64];
# snprintf(for_block_name, sizeof for_block_name, "$ivl_foreach%u", foreach_counter);
# foreach_counter += 1;
- #
+ #
# PBlock*tmp = pform_push_block_scope(for_block_name, PBlock::BL_SEQ);
# FILE_NAME(tmp, @1);
# current_block_stack.push(tmp);
- #
+ #
# pform_make_foreach_declarations(@1, $5);
# }
()
# use_port_type = port_declaration_context.port_type;
# perm_string name = lex_strings.make($3);
# list<perm_string>* ilist = list_from_identifier($3);
- #
+ #
# if (use_port_type == NetNet::PIMPLICIT) {
# yyerror(@1, "error: missing task/function port direction.");
# use_port_type = NetNet::PINPUT; // for error recovery
# tmp = pform_make_task_ports(@3, use_port_type,
# port_declaration_context.data_type,
# ilist);
- #
+ #
# } else {
# // Otherwise, the decorations for this identifier
# // indicate the type. Save the type for any right
# if ($4 != 0) {
# pform_set_reg_idx(name, $4);
# }
- #
+ #
# $$ = tmp;
# if ($5) {
# assert(tmp->size()==1);
# tmp->push_back(index);
# $$ = tmp;
# }
+ # XXX TODO: subscriptlist
+ start = str(p[4])
+ end = str(p[2])
+ if end.endswith("-1"):
+ end = end[:-2]
+ elif end.isdigit():
+ end = str(int(end)+1)
+ else:
+ end = "1+%s" % end
+ p[0] = '[%s:%s]' % (start, end) # python slice is LO:HI+1
()
def p_variable_dimension_2(p):
'''variable_dimension : '[' expression ']' '''
# { perm_string name = lex_strings.make($3.text);
# if (pform_test_type_identifier_local(name)) {
# yyerror(@3, "error: Typedef identifier \"%s\" is already a type name.", $3.text);
- #
+ #
# } else {
# pform_set_typedef(name, $2, NULL);
# }
'''delay_value_simple : TIME_LITERAL '''
print('delay_value_simple_4', list(p))
# { int unit;
- #
+ #
# based_size = 0;
# $$ = 0;
# if ($1 == 0 || !get_time_unit($1, unit))
# double p = pow(10.0,
# (double)(unit - pform_get_timeunit()));
# double time = atof($1) * p;
- #
+ #
# verireal *v = new verireal(time);
# $$ = new PEFNumber(v);
# FILE_NAME($$, @1);
# FILE_NAME(tmp, @2);
# $$ = tmp;
# }
+ p[0] = Node(syms.atom, [p[1], Leaf(token.MINUS, '-'), p[4]])
()
def p_expression_26(p):
'''expression : expression '&' attribute_list_opt expression '''
'''expr_primary : TIME_LITERAL '''
print('expr_primary_4', list(p))
# { int unit;
- #
+ #
# based_size = 0;
# $$ = 0;
# if ($1 == 0 || !get_time_unit($1, unit))
# else {
# double p = pow(10.0, (double)(unit - pform_get_timeunit()));
# double time = atof($1) * p;
- #
+ #
# verireal *v = new verireal(time);
# $$ = new PEFNumber(v);
# FILE_NAME($$, @1);
def p_list_of_port_declarations_1(p):
'''list_of_port_declarations : port_declaration '''
print('list_of_port_declarations_1', list(p))
+ p[0] = [p[1]]
# { vector<Module::port_t*>*tmp
# = new vector<Module::port_t*>(1);
# (*tmp)[0] = $1;
def p_list_of_port_declarations_2(p):
'''list_of_port_declarations : list_of_port_declarations ',' port_declaration '''
print('list_of_port_declarations_2', list(p))
+ p[1].append(Leaf(token.NEWLINE, '\n')) # should be a comma
+ # XXX p[3].prefix=' ' # add a space after the NL, must go in parameter
+ p[1].append(p[3])
+ p[0] = p[1]
# { vector<Module::port_t*>*tmp = $1;
# tmp->push_back($3);
# $$ = tmp;
# @3.first_line);
# vector<Module::port_t*>*tmp = $1;
# tmp->push_back(ptmp);
- #
+ #
# /* Get the port declaration details, the port type
# and what not, from context data stored by the
# last port_declaration rule. */
def p_port_declaration_1(p):
'''port_declaration : attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER dimensions_opt '''
print('port_declaration_1', list(p))
+ # XXX TODO: python AST
+ comment, dt, name = p[2], p[4], p[5]
+ p[0] = port_decl(comment, dt, name)
# { Module::port_t*ptmp;
# perm_string name = lex_strings.make($5);
# data_type_t*use_type = $4;
def p_port_declaration_5(p):
'''port_declaration : attribute_list_opt K_output net_type_opt data_type_or_implicit IDENTIFIER dimensions_opt '''
print('port_declaration_5', list(p))
+ # XXX TODO: python AST
+ comment, dt, name = p[2], p[4], p[5]
+ p[0] = port_decl(comment, dt, name)
# { Module::port_t*ptmp;
# perm_string name = lex_strings.make($5);
# data_type_t*use_dtype = $4;
# use_type = NetNet::IMPLICIT;
# else
# use_type = NetNet::IMPLICIT_REG;
- #
+ #
# // The SystemVerilog types that can show up as
# // output ports are implicitly (on the inside)
# // variables because "reg" is not valid syntax
# port_declaration_context.port_type = NetNet::PINOUT;
# port_declaration_context.port_net_type = use_type;
# port_declaration_context.data_type = $4;
- #
+ #
# pform_make_var_init(@5, name, $7);
- #
+ #
# delete[]$5;
# $$ = ptmp;
# }
def p_net_type_opt_2(p):
'''net_type_opt : '''
print('net_type_opt_2', list(p))
- # { $$ = NetNet::IMPLICIT; }
+ p[0] = NN_IMPLICIT
()
def p_unsigned_signed_opt_1(p):
'''unsigned_signed_opt : K_signed '''
else:
stmts = Node(syms.small_stmt, [pass_stmt, Leaf(token.NEWLINE, '\n')])
stmts = Node(syms.stmt, [stmts])
+
+ # XXX TODO ports as py nodes
+ ports = p[8]
+ stmts.children.append(Leaf(token.STRING, '\n' + indent(ports, 8)))
suite = Node(syms.suite, [Leaf(token.NEWLINE, '\n'),
Leaf(token.INDENT, ' '),
stmts,
Leaf(token.DEDENT, '')
])
- clsdecl = Node(syms.classdef, clsname + [suite],
- prefix='', fixers_applied=[])
+ clsdecl = Node(syms.classdef, clsname + [suite])
clsdecl = Node(syms.compound_stmt, [clsdecl])
print ("clsdecl", repr(clsdecl))
print ("clsstr:")
'''module_parameter_port_list : module_parameter_port_list ',' K_parameter param_type parameter_assign '''
print('module_parameter_port_list_3', list(p))
p[1].append(Leaf(token.COMMA, ','))
- p[5].prefix=' ' # add a space after the comma, must go in the parameter
+ p[1].append(Leaf(token.NEWLINE, '\n'))
+ p[5].prefix=' ' # add space after newline
p[1].append(p[5])
p[0] = p[1]
()
# use_type = NetNet::REG;
# else
# use_type = NetNet::IMPLICIT_REG;
- #
+ #
# // The SystemVerilog types that can show up as
# // output ports are implicitly (on the inside)
# // variables because "reg" is not valid syntax
# { assert($2);
# PENumber*tmp = new PENumber($2);
# FILE_NAME(tmp, @1);
- #
+ #
# struct parmvalue_t*lst = new struct parmvalue_t;
# lst->by_order = new list<PExpr*>;
# lst->by_order->push_back(tmp);
# { assert($2);
# PEFNumber*tmp = new PEFNumber($2);
# FILE_NAME(tmp, @1);
- #
+ #
# struct parmvalue_t*lst = new struct parmvalue_t;
# lst->by_order = new list<PExpr*>;
# lst->by_order->push_back(tmp);
# itmp.sel = index_component_t::SEL_PART;
# itmp.msb = $3;
# itmp.lsb = $5;
- #
+ #
# name_component_t ntmp (lex_strings.make($1));
# ntmp.index.push_back(itmp);
- #
+ #
# pform_name_t pname;
# pname.push_back(ntmp);
- #
+ #
# PEIdent*wtmp = new PEIdent(pname);
# FILE_NAME(wtmp, @1);
- #
+ #
# Module::port_t*ptmp = new Module::port_t;
# ptmp->name = perm_string();
# ptmp->expr.push_back(wtmp);
- #
+ #
# delete[]$1;
# $$ = ptmp;
# }
# itmp.sel = index_component_t::SEL_BIT;
# itmp.msb = $3;
# itmp.lsb = 0;
- #
+ #
# name_component_t ntmp (lex_strings.make($1));
# ntmp.index.push_back(itmp);
- #
+ #
# pform_name_t pname;
# pname.push_back(ntmp);
- #
+ #
# PEIdent*tmp = new PEIdent(pname);
# FILE_NAME(tmp, @1);
- #
+ #
# Module::port_t*ptmp = new Module::port_t;
# ptmp->name = perm_string();
# ptmp->expr.push_back(tmp);