Skip to content

Commit

Permalink
Implement static arrays of strings.
Browse files Browse the repository at this point in the history
This means extending the vvp to add .array/str objects and
include instructions to access the array. Also add the parser
and code generator support.
  • Loading branch information
steveicarus committed Jan 5, 2013
1 parent d6726f6 commit 074055b
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 19 deletions.
18 changes: 16 additions & 2 deletions tgt-vvp/eval_string.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/ */


# include "vvp_priv.h" # include "vvp_priv.h"
# include <string.h>
# include <assert.h> # include <assert.h>


static void fallback_eval(ivl_expr_t expr) static void fallback_eval(ivl_expr_t expr)
Expand Down Expand Up @@ -63,12 +64,25 @@ static void string_ex_signal(ivl_expr_t expr)
{ {
ivl_signal_t sig = ivl_expr_signal(expr); ivl_signal_t sig = ivl_expr_signal(expr);


if (ivl_signal_data_type(sig) == IVL_VT_STRING) { if (ivl_signal_data_type(sig) != IVL_VT_STRING) {
fallback_eval(expr);
return;
}

/* Simple case: This is a simple variable. Generate a load
statement to load the string into the stack. */
if (ivl_signal_dimensions(sig) == 0) {
fprintf(vvp_out, " %%load/str v%p_0;\n", sig); fprintf(vvp_out, " %%load/str v%p_0;\n", sig);
return; return;
} }


fallback_eval(expr); /* There is a word select expression, so load the index into a
register and load from the array. */
ivl_expr_t word_ex = ivl_expr_oper1(expr);
int word_ix = allocate_word();
draw_eval_expr_into_integer(word_ex, word_ix);
fprintf(vvp_out, " %%load/stra v%p, %d;\n", sig, word_ix);
clr_word(word_ix);
} }


static void string_ex_select(ivl_expr_t expr) static void string_ex_select(ivl_expr_t expr)
Expand Down
15 changes: 14 additions & 1 deletion tgt-vvp/stmt_assign.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -730,6 +730,7 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
ivl_lval_t lval = ivl_stmt_lval(net, 0); ivl_lval_t lval = ivl_stmt_lval(net, 0);
ivl_expr_t rval = ivl_stmt_rval(net); ivl_expr_t rval = ivl_stmt_rval(net);
ivl_expr_t part = ivl_lval_part_off(lval); ivl_expr_t part = ivl_lval_part_off(lval);
ivl_expr_t aidx = ivl_lval_idx(lval);
ivl_signal_t var= ivl_lval_sig(lval); ivl_signal_t var= ivl_lval_sig(lval);


assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_lvals(net) == 1);
Expand All @@ -739,12 +740,24 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
/* Simplest case: no mux. Evaluate the r-value as a string and /* Simplest case: no mux. Evaluate the r-value as a string and
store the result into the variable. Note that the store the result into the variable. Note that the
%store/str opcode pops the string result. */ %store/str opcode pops the string result. */
if (part == 0) { if (part == 0 && aidx == 0) {
draw_eval_string(rval); draw_eval_string(rval);
fprintf(vvp_out, " %%store/str v%p_0;\n", var); fprintf(vvp_out, " %%store/str v%p_0;\n", var);
return 0; return 0;
} }


/* Assign to array. The l-value has an index expression
expression so we are assigning to an array word. */
if (aidx != 0) {
unsigned ix;
assert(part == 0);
draw_eval_string(rval);
draw_eval_expr_into_integer(aidx, (ix = allocate_word()));
fprintf(vvp_out, " %%store/stra v%p, %u;\n", var, ix);
clr_word(ix);
return 0;
}

/* Calculate the character select for the word. */ /* Calculate the character select for the word. */
int mux_word = allocate_word(); int mux_word = allocate_word();
draw_eval_expr_into_integer(part, mux_word); draw_eval_expr_into_integer(part, mux_word);
Expand Down
21 changes: 20 additions & 1 deletion tgt-vvp/vvp_scope.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ static void draw_reg_in_scope(ivl_signal_t sig)
const char *datatype_flag = ivl_signal_integer(sig) ? "/i" : const char *datatype_flag = ivl_signal_integer(sig) ? "/i" :
ivl_signal_signed(sig)? "/s" : ""; ivl_signal_signed(sig)? "/s" : "";
const char *local_flag = local_flag_str(sig); const char *local_flag = local_flag_str(sig);
int vector_dims = 1;


switch (ivl_signal_data_type(sig)) { switch (ivl_signal_data_type(sig)) {
case IVL_VT_BOOL: case IVL_VT_BOOL:
Expand All @@ -485,14 +486,32 @@ static void draw_reg_in_scope(ivl_signal_t sig)
break; break;
case IVL_VT_REAL: case IVL_VT_REAL:
datatype_flag = "/real"; datatype_flag = "/real";
vector_dims = 0;
break;
case IVL_VT_STRING:
datatype_flag = "/str";
vector_dims = 0;
break; break;
default: default:
break; break;
} }


/* If the reg objects are collected into an array, then first /* If the reg objects are collected into an array, then first
write out the .array record to declare the array indices. */ write out the .array record to declare the array indices. */
if (ivl_signal_dimensions(sig) > 0) { if (ivl_signal_dimensions(sig) > 0 && vector_dims==0) {

/* Some types cannot be placed in packed dimensions, so
do not include packed dimensions. */
unsigned word_count = ivl_signal_array_count(sig);
unsigned swapped = ivl_signal_array_addr_swapped(sig);
int last = ivl_signal_array_base(sig)+word_count-1;
int first = ivl_signal_array_base(sig);
fprintf(vvp_out, "v%p .array%s \"%s\", %d %d;\n",
sig, datatype_flag,
vvp_mangle_name(ivl_signal_basename(sig)),
swapped ? first: last, swapped ? last : first);

} else if (ivl_signal_dimensions(sig) > 0) {
unsigned word_count = ivl_signal_array_count(sig); unsigned word_count = ivl_signal_array_count(sig);
unsigned swapped = ivl_signal_array_addr_swapped(sig); unsigned swapped = ivl_signal_array_addr_swapped(sig);
int last = ivl_signal_array_base(sig)+word_count-1; int last = ivl_signal_array_base(sig)+word_count-1;
Expand Down
83 changes: 74 additions & 9 deletions vvp/array.cc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -802,23 +802,39 @@ static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref)
} }


// This function return true if the underlying array words are real. // This function return true if the underlying array words are real.
static unsigned vpi_array_is_real(vvp_array_t arr) static bool vpi_array_is_real(vvp_array_t arr)
{ {
// Check to see if this is a variable/register array. // Check to see if this is a variable/register array.
if (arr->vals4 != 0) return 0U; // A bit based variable/register array. if (arr->vals4 != 0) // A bit based variable/register array.
return false;


if (dynamic_cast<vvp_darray_real*> (arr->vals)) if (dynamic_cast<vvp_darray_real*> (arr->vals))
return 1U; return true;

if (arr->vals != 0)
return false;


// This must be a net array so look at element 0 to find the type. // This must be a net array so look at element 0 to find the type.
assert(arr->nets != 0); assert(arr->nets != 0);
assert(arr->array_count > 0); assert(arr->array_count > 0);
struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]); struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]);
if (rsig) { if (rsig) {
return 1U; return true;
} }


return 0U; return false;
}

static bool vpi_array_is_string(vvp_array_t arr)
{
// Check to see if this is a variable/register array.
if (arr->vals4 != 0) // A bit based variable/register array.
return false;

if (dynamic_cast<vvp_darray_string*> (arr->vals))
return true;

return false;
} }


static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp) static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp)
Expand All @@ -833,6 +849,9 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp)
if (vpi_array_is_real(parent)) { if (vpi_array_is_real(parent)) {
double tmp = array_get_word_r(parent, index); double tmp = array_get_word_r(parent, index);
vpip_real_get_value(tmp, vp); vpip_real_get_value(tmp, vp);
} else if (vpi_array_is_string(parent)) {
string tmp = array_get_word_str(parent, index);
vpip_string_get_value(tmp, vp);
} else { } else {
vvp_vector4_t tmp = array_get_word(parent, index); vvp_vector4_t tmp = array_get_word(parent, index);
unsigned width = get_array_word_size(parent); unsigned width = get_array_word_size(parent);
Expand Down Expand Up @@ -1025,6 +1044,18 @@ void array_set_word(vvp_array_t arr, unsigned address, double val)
array_word_change(arr, address); array_word_change(arr, address);
} }


void array_set_word(vvp_array_t arr, unsigned address, const string&val)
{
assert(arr->vals != 0);
assert(arr->nets == 0);

if (address >= arr->vals->get_size())
return;

arr->vals->set_word(address, val);
array_word_change(arr, address);
}

vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
{ {
if (arr->vals4) { if (arr->vals4) {
Expand Down Expand Up @@ -1099,6 +1130,27 @@ double array_get_word_r(vvp_array_t arr, unsigned address)


} }


string array_get_word_str(vvp_array_t arr, unsigned address)
{
if (arr->vals) {
assert(arr->vals4 == 0);
assert(arr->nets == 0);
// In this context, address out of bounds returns 0.0
// instead of an error.
if (address >= arr->vals->get_size())
return "";

string val;
arr->vals->get_word(address, val);
return val;
}

assert(arr->nets);
// Arrays of string nets not implemented!
assert(0);
return "";
}

static vpiHandle vpip_make_array(char*label, const char*name, static vpiHandle vpip_make_array(char*label, const char*name,
int first_addr, int last_addr, int first_addr, int last_addr,
bool signed_flag) bool signed_flag)
Expand Down Expand Up @@ -1265,8 +1317,7 @@ void compile_var2_array(char*label, char*name, int last, int first,
delete[] name; delete[] name;
} }


void compile_real_array(char*label, char*name, int last, int first, void compile_real_array(char*label, char*name, int last, int first)
int msb, int lsb)
{ {
vpiHandle obj = vpip_make_array(label, name, first, last, true); vpiHandle obj = vpip_make_array(label, name, first, last, true);


Expand All @@ -1276,8 +1327,22 @@ void compile_real_array(char*label, char*name, int last, int first,
arr->vals = new vvp_darray_real(arr->array_count); arr->vals = new vvp_darray_real(arr->array_count);
arr->vals_width = 1; arr->vals_width = 1;


/* For a real array the MSB and LSB must be zero. */ count_real_arrays += 1;
assert(msb == 0 && lsb == 0); count_real_array_words += arr->array_count;

free(label);
delete[] name;
}

void compile_string_array(char*label, char*name, int last, int first)
{
vpiHandle obj = vpip_make_array(label, name, first, last, true);

struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);

/* Make the words. */
arr->vals = new vvp_darray_string(arr->array_count);
arr->vals_width = 1;


count_real_arrays += 1; count_real_arrays += 1;
count_real_array_words += arr->array_count; count_real_array_words += arr->array_count;
Expand Down
3 changes: 3 additions & 0 deletions vvp/array.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ extern void array_set_word(vvp_array_t arr, unsigned idx,
unsigned off, vvp_vector4_t val); unsigned off, vvp_vector4_t val);
extern void array_set_word(vvp_array_t arr, unsigned idx, extern void array_set_word(vvp_array_t arr, unsigned idx,
double val); double val);
extern void array_set_word(vvp_array_t arr, unsigned idx,
const std::string&val);


extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address); extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address);
extern double array_get_word_r(vvp_array_t array, unsigned address); extern double array_get_word_r(vvp_array_t array, unsigned address);
extern std::string array_get_word_str(vvp_array_t array, unsigned address);


/* VPI hooks */ /* VPI hooks */


Expand Down
2 changes: 2 additions & 0 deletions vvp/codes.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ extern bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_OBJ(vthread_t thr, vvp_code_t code); extern bool of_LOAD_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STRA(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VP0_S(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0_S(vthread_t thr, vvp_code_t code);
Expand Down Expand Up @@ -186,6 +187,7 @@ extern bool of_STORE_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code); extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code);
extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code); extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STR(vthread_t thr, vvp_code_t code); extern bool of_STORE_STR(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STRA(vthread_t thr, vvp_code_t code);
extern bool of_SUB(vthread_t thr, vvp_code_t code); extern bool of_SUB(vthread_t thr, vvp_code_t code);
extern bool of_SUB_WR(vthread_t thr, vvp_code_t code); extern bool of_SUB_WR(vthread_t thr, vvp_code_t code);
extern bool of_SUBI(vthread_t thr, vvp_code_t code); extern bool of_SUBI(vthread_t thr, vvp_code_t code);
Expand Down
2 changes: 2 additions & 0 deletions vvp/compile.cc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} }, { "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
{ "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%load/stra", of_LOAD_STRA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
Expand Down Expand Up @@ -233,6 +234,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} }, { "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/stra", of_STORE_STRA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
Expand Down
5 changes: 3 additions & 2 deletions vvp/compile.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -348,8 +348,9 @@ extern void compile_var2_array(char*label, char*name,
int last, int first, int last, int first,
int msb, int lsb, bool signed_flag); int msb, int lsb, bool signed_flag);
extern void compile_real_array(char*label, char*name, extern void compile_real_array(char*label, char*name,
int last, int first, int last, int first);
int msb, int lsb); extern void compile_string_array(char*label, char*name,
int last, int first);
extern void compile_net_array(char*label, char*name, extern void compile_net_array(char*label, char*name,
int last, int first); int last, int first);
extern void compile_array_alias(char*label, char*name, char*src); extern void compile_array_alias(char*label, char*name, char*src);
Expand Down
1 change: 1 addition & 0 deletions vvp/lexor.lex
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ static char* strdupnew(char const *str)
".array/i" { return K_ARRAY_I; } ".array/i" { return K_ARRAY_I; }
".array/real" { return K_ARRAY_R; } ".array/real" { return K_ARRAY_R; }
".array/s" { return K_ARRAY_S; } ".array/s" { return K_ARRAY_S; }
".array/str" { return K_ARRAY_STR; }
".array/port" { return K_ARRAY_PORT; } ".array/port" { return K_ARRAY_PORT; }
".cast/2" { return K_CAST_2; } ".cast/2" { return K_CAST_2; }
".cast/int" { return K_CAST_INT; } ".cast/int" { return K_CAST_INT; }
Expand Down
6 changes: 5 additions & 1 deletion vvp/opcodes.txt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ The %load/real instruction reads a real value from the vpi-like object
and pushes it to the top of the real value stack. and pushes it to the top of the real value stack.


* %load/str <var-label> * %load/str <var-label>
* %load/stra <array-label>, <index>
* %load/dar/str <var-label> * %load/dar/str <var-label>


The %load/str instruction gets the string from the string variable and The %load/str instruction gets the string from the string variable and
Expand Down Expand Up @@ -1009,7 +1010,7 @@ variable given by the label.
See also %load/obj. See also %load/obj.


* %store/real <var-label> * %store/real <var-label>
* %store/reala <var-label> <index> * %store/reala <var-label>, <index>


This pops the top of the real variable stack and write it to the This pops the top of the real variable stack and write it to the
object variable given bu the label. object variable given bu the label.
Expand All @@ -1018,12 +1019,15 @@ The areal version is similar, but writes to a real array using the
index in the index register <index> index in the index register <index>


* %store/str <var-label> * %store/str <var-label>
* %store/stra <array-label>, <index>
* %store/dar/r <var-label> * %store/dar/r <var-label>
* %store/dar/str <var-label> * %store/dar/str <var-label>


The %store/str instruction pops the top of the string stack and writes The %store/str instruction pops the top of the string stack and writes
it to the string variable. it to the string variable.


The %store/stra targets an array.

The %store/dar/str is similar, but the target is a dynamic array of The %store/dar/str is similar, but the target is a dynamic array of
string string. The index is taken from signed index register 3. string string. The index is taken from signed index register 3.


Expand Down
9 changes: 6 additions & 3 deletions vvp/parse.y
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_ARITH_MOD_R K_ARITH_MOD_S %token K_ARITH_MOD_R K_ARITH_MOD_S
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R %token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S %token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
%token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT %token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_STR K_ARRAY_PORT
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2 %token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
%token K_CLASS %token K_CLASS
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R %token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
Expand Down Expand Up @@ -221,12 +221,15 @@ statement
| T_LABEL K_ARRAY_I T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY_I T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';'
{ compile_var_array($1, $3, $5, $6, $8, $9, 2); } { compile_var_array($1, $3, $5, $6, $8, $9, 2); }


| T_LABEL K_ARRAY_R T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY_R T_STRING ',' signed_t_number signed_t_number ';'
{ compile_real_array($1, $3, $5, $6, $8, $9); } { compile_real_array($1, $3, $5, $6); }


| T_LABEL K_ARRAY_S T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY_S T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';'
{ compile_var_array($1, $3, $5, $6, $8, $9, 1); } { compile_var_array($1, $3, $5, $6, $8, $9, 1); }


| T_LABEL K_ARRAY_STR T_STRING ',' signed_t_number signed_t_number ';'
{ compile_string_array($1, $3, $5, $6); }

| T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ';'
{ compile_net_array($1, $3, $5, $6); } { compile_net_array($1, $3, $5, $6); }


Expand Down
Loading

0 comments on commit 074055b

Please sign in to comment.