1 /*
2  * Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com)
3  *
4  *    This source code is free software; you can redistribute it
5  *    and/or modify it in source code form under the terms of the GNU
6  *    General Public License as published by the Free Software
7  *    Foundation; either version 2 of the License, or (at your option)
8  *    any later version.
9  *
10  *    This program is distributed in the hope that it will be useful,
11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *    GNU General Public License for more details.
14  *
15  *    You should have received a copy of the GNU General Public License
16  *    along with this program; if not, write to the Free Software
17  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 
21 # include  "config.h"
22 # include  "delay.h"
23 # include  "arith.h"
24 # include  "compile.h"
25 # include  "logic.h"
26 # include  "resolv.h"
27 # include  "udp.h"
28 # include  "symbols.h"
29 # include  "codes.h"
30 # include  "schedule.h"
31 # include  "vpi_priv.h"
32 # include  "parse_misc.h"
33 # include  "statistics.h"
34 # include  "schedule.h"
35 # include  <iostream>
36 # include  <list>
37 # include  <cstdlib>
38 # include  <cstring>
39 # include  <cassert>
40 
41 #ifdef __MINGW32__
42 #include <windows.h>
43 #endif
44 
45 # include  "ivl_alloc.h"
46 
47 unsigned compile_errors = 0;
48 
49 /*
50  * The opcode table lists all the code mnemonics, along with their
51  * opcode and operand types. The table is written sorted by mnemonic
52  * so that it can be searched by binary search. The opcode_compare
53  * function is a helper function for that lookup.
54  */
55 
56 enum operand_e {
57 	/* Place holder for unused operand */
58       OA_NONE,
59 	/* The operand is a number, an immediate unsigned integer */
60       OA_NUMBER,
61 	/* The operand is a pointer to an array. */
62       OA_ARR_PTR,
63 	/* The operand is a thread bit index or short integer */
64       OA_BIT1,
65       OA_BIT2,
66 	/* The operand is a pointer to code space */
67       OA_CODE_PTR,
68       OA_CODE_PTR2,
69 	/* The operand is a variable or net pointer */
70       OA_FUNC_PTR,
71 	/* The operand is a second functor pointer */
72       OA_FUNC_PTR2,
73 	/* The operand is a VPI handle */
74       OA_VPI_PTR,
75 	/* String */
76       OA_STRING
77 };
78 
79 struct opcode_table_s {
80       const char*mnemonic;
81       vvp_code_fun opcode;
82 
83       unsigned argc;
84       enum operand_e argt[OPERAND_MAX];
85 };
86 
87 static const struct opcode_table_s opcode_table[] = {
88       { "%abs/wr", of_ABS_WR, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
89       { "%add",    of_ADD,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
90       { "%add/wr", of_ADD_WR, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
91       { "%addi",   of_ADDI,   3,  {OA_BIT1,     OA_BIT2,     OA_NUMBER} },
92       { "%alloc",  of_ALLOC,  1,  {OA_VPI_PTR,  OA_NONE,     OA_NONE} },
93       { "%and",    of_AND,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
94       { "%and/r",  of_ANDR,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
95       { "%assign/ar",of_ASSIGN_AR,2,{OA_ARR_PTR,OA_BIT1,     OA_NONE} },
96       { "%assign/ar/d",of_ASSIGN_ARD,2,{OA_ARR_PTR,OA_BIT1,  OA_NONE} },
97       { "%assign/ar/e",of_ASSIGN_ARE,1,{OA_ARR_PTR,OA_NONE,  OA_NONE} },
98       { "%assign/vec4",      of_ASSIGN_VEC4,       2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
99       { "%assign/vec4/a/d",  of_ASSIGN_VEC4_A_D,   3, {OA_ARR_PTR,  OA_BIT1, OA_BIT2} },
100       { "%assign/vec4/a/e",  of_ASSIGN_VEC4_A_E,   2, {OA_ARR_PTR,  OA_BIT1, OA_NONE} },
101       { "%assign/vec4/d",    of_ASSIGN_VEC4D,      2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
102       { "%assign/vec4/e",    of_ASSIGN_VEC4E,      1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
103       { "%assign/vec4/off/d",of_ASSIGN_VEC4_OFF_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
104       { "%assign/vec4/off/e",of_ASSIGN_VEC4_OFF_E, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
105       { "%assign/wr",  of_ASSIGN_WR, 2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
106       { "%assign/wr/d",of_ASSIGN_WRD,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
107       { "%assign/wr/e",of_ASSIGN_WRE,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
108       { "%blend",    of_BLEND,   0,  {OA_NONE,  OA_NONE,     OA_NONE} },
109       { "%blend/wr", of_BLEND_WR,0,  {OA_NONE,  OA_NONE,     OA_NONE} },
110       { "%breakpoint", of_BREAKPOINT, 0,  {OA_NONE, OA_NONE, OA_NONE} },
111       { "%callf/obj",       of_CALLF_OBJ,       2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
112       { "%callf/real",      of_CALLF_REAL,      2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
113       { "%callf/str",       of_CALLF_STR,       2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
114       { "%callf/vec4",      of_CALLF_VEC4,      2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
115       { "%callf/void",      of_CALLF_VOID,      2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
116       { "%cassign/link",    of_CASSIGN_LINK,    2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
117       { "%cassign/vec4",    of_CASSIGN_VEC4,    1,{OA_FUNC_PTR,OA_NONE,     OA_NONE} },
118       { "%cassign/vec4/off",of_CASSIGN_VEC4_OFF,2,{OA_FUNC_PTR,OA_BIT1,     OA_NONE} },
119       { "%cassign/wr",  of_CASSIGN_WR,  1,{OA_FUNC_PTR,OA_NONE,     OA_NONE} },
120       { "%cast/vec2/dar", of_CAST_VEC2_DAR, 1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
121       { "%cast/vec4/dar", of_CAST_VEC4_DAR, 1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
122       { "%cast/vec4/str", of_CAST_VEC4_STR, 1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
123       { "%cast2",   of_CAST2,  0,  {OA_NONE,     OA_NONE,     OA_NONE} },
124       { "%cmp/e",   of_CMPE,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
125       { "%cmp/ne",  of_CMPNE,  0,  {OA_NONE,     OA_NONE,     OA_NONE} },
126       { "%cmp/s",   of_CMPS,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
127       { "%cmp/str", of_CMPSTR, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
128       { "%cmp/u",   of_CMPU,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
129       { "%cmp/we",  of_CMPWE,  0,  {OA_NONE,     OA_NONE,     OA_NONE} },
130       { "%cmp/wne", of_CMPWNE, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
131       { "%cmp/wr",  of_CMPWR,  0,  {OA_NONE,     OA_NONE,     OA_NONE} },
132       { "%cmp/ws",  of_CMPWS,  2,  {OA_BIT1,     OA_BIT2,     OA_NONE} },
133       { "%cmp/wu",  of_CMPWU,  2,  {OA_BIT1,     OA_BIT2,     OA_NONE} },
134       { "%cmp/x",   of_CMPX,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
135       { "%cmp/z",   of_CMPZ,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
136       { "%cmpi/e",  of_CMPIE,  3,  {OA_BIT1,     OA_BIT2,     OA_NUMBER} },
137       { "%cmpi/ne", of_CMPINE, 3,  {OA_BIT1,     OA_BIT2,     OA_NUMBER} },
138       { "%cmpi/s",  of_CMPIS,  3,  {OA_BIT1,     OA_BIT2,     OA_NUMBER} },
139       { "%cmpi/u",  of_CMPIU,  3,  {OA_BIT1,     OA_BIT2,     OA_NUMBER} },
140       { "%concat/str",  of_CONCAT_STR,  0,{OA_NONE,  OA_NONE,  OA_NONE} },
141       { "%concat/vec4", of_CONCAT_VEC4, 0,{OA_NONE,  OA_NONE,  OA_NONE} },
142       { "%concati/str", of_CONCATI_STR, 1,{OA_STRING,OA_NONE,  OA_NONE} },
143       { "%concati/vec4",of_CONCATI_VEC4,3,{OA_BIT1,  OA_BIT2,  OA_NUMBER} },
144       { "%cvt/rv",   of_CVT_RV,  0, {OA_NONE,   OA_NONE,     OA_NONE} },
145       { "%cvt/rv/s", of_CVT_RV_S,0, {OA_NONE,   OA_NONE,     OA_NONE} },
146       { "%cvt/sr", of_CVT_SR, 1,  {OA_BIT1,     OA_NONE,     OA_NONE} },
147       { "%cvt/ur", of_CVT_UR, 1,  {OA_BIT1,     OA_NONE,     OA_NONE} },
148       { "%cvt/vr", of_CVT_VR, 1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
149       { "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1,     OA_BIT2} },
150       { "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE,     OA_NONE} },
151       { "%debug/thr",  of_DEBUG_THR,  1,{OA_STRING,   OA_NONE,     OA_NONE} },
152       { "%delay",  of_DELAY,  2,  {OA_BIT1,     OA_BIT2,     OA_NONE} },
153       { "%delayx", of_DELAYX, 1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
154       { "%delete/elem",of_DELETE_ELEM,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
155       { "%delete/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE,  OA_NONE} },
156       { "%delete/tail",of_DELETE_TAIL,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
157       { "%disable",  of_DISABLE, 1, {OA_VPI_PTR,OA_NONE,     OA_NONE} },
158       { "%disable/fork",of_DISABLE_FORK,0,{OA_NONE,OA_NONE,  OA_NONE} },
159       { "%div",      of_DIV,     0, {OA_NONE,   OA_NONE,     OA_NONE} },
160       { "%div/s",    of_DIV_S,   0, {OA_NONE,   OA_NONE,     OA_NONE} },
161       { "%div/wr",   of_DIV_WR,  0, {OA_NONE,   OA_NONE,     OA_NONE} },
162       { "%dup/real", of_DUP_REAL,0, {OA_NONE,   OA_NONE,     OA_NONE} },
163       { "%dup/vec4", of_DUP_VEC4,0, {OA_NONE,   OA_NONE,     OA_NONE} },
164       { "%end",    of_END,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
165       { "%evctl",  of_EVCTL,  2,  {OA_FUNC_PTR, OA_BIT1,     OA_NONE} },
166       { "%evctl/c",of_EVCTLC, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
167       { "%evctl/i",of_EVCTLI, 2,  {OA_FUNC_PTR, OA_BIT1,     OA_NONE} },
168       { "%evctl/s",of_EVCTLS, 2,  {OA_FUNC_PTR, OA_BIT1,     OA_NONE} },
169       { "%event",  of_EVENT,  1,  {OA_FUNC_PTR, OA_NONE,     OA_NONE} },
170       { "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
171       { "%flag_inv",      of_FLAG_INV,      1, {OA_BIT1,   OA_NONE, OA_NONE} },
172       { "%flag_mov",      of_FLAG_MOV,      2, {OA_BIT1,   OA_BIT2, OA_NONE} },
173       { "%flag_or",       of_FLAG_OR,       2, {OA_BIT1,   OA_BIT2, OA_NONE} },
174       { "%flag_set/imm",  of_FLAG_SET_IMM,  2, {OA_NUMBER, OA_BIT1, OA_NONE} },
175       { "%flag_set/vec4", of_FLAG_SET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
176       { "%force/link",    of_FORCE_LINK,2,{OA_FUNC_PTR, OA_FUNC_PTR2, OA_NONE} },
177       { "%force/vec4",    of_FORCE_VEC4,    1,{OA_FUNC_PTR, OA_NONE,      OA_NONE} },
178       { "%force/vec4/off",of_FORCE_VEC4_OFF,2,{OA_FUNC_PTR, OA_BIT1,      OA_NONE} },
179       { "%force/vec4/off/d",of_FORCE_VEC4_OFF_D,3,{OA_FUNC_PTR, OA_BIT1,  OA_BIT2} },
180       { "%force/wr",      of_FORCE_WR,      1,{OA_FUNC_PTR, OA_NONE,      OA_NONE} },
181       { "%fork",   of_FORK,   2,  {OA_CODE_PTR2,OA_VPI_PTR,  OA_NONE} },
182       { "%free",   of_FREE,   1,  {OA_VPI_PTR,  OA_NONE,     OA_NONE} },
183       { "%inv",    of_INV,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
184       { "%ix/add", of_IX_ADD, 3,  {OA_NUMBER,   OA_BIT1,     OA_BIT2} },
185       { "%ix/getv",of_IX_GETV,2,  {OA_BIT1,     OA_FUNC_PTR, OA_NONE} },
186       { "%ix/getv/s",of_IX_GETV_S,2, {OA_BIT1,   OA_FUNC_PTR, OA_NONE} },
187       { "%ix/load",of_IX_LOAD,3,  {OA_NUMBER,   OA_BIT1,     OA_BIT2} },
188       { "%ix/mov", of_IX_MOV, 2,  {OA_BIT1,     OA_BIT2,     OA_NONE} },
189       { "%ix/mul", of_IX_MUL, 3,  {OA_NUMBER,   OA_BIT1,     OA_BIT2} },
190       { "%ix/sub", of_IX_SUB, 3,  {OA_NUMBER,   OA_BIT1,     OA_BIT2} },
191       { "%ix/vec4",  of_IX_VEC4,  1,  {OA_NUMBER,   OA_NONE, OA_NONE} },
192       { "%ix/vec4/s",of_IX_VEC4_S,1,  {OA_NUMBER,   OA_NONE, OA_NONE} },
193       { "%jmp",    of_JMP,    1,  {OA_CODE_PTR, OA_NONE,     OA_NONE} },
194       { "%jmp/0",  of_JMP0,   2,  {OA_CODE_PTR, OA_BIT1,     OA_NONE} },
195       { "%jmp/0xz",of_JMP0XZ, 2,  {OA_CODE_PTR, OA_BIT1,     OA_NONE} },
196       { "%jmp/1",  of_JMP1,   2,  {OA_CODE_PTR, OA_BIT1,     OA_NONE} },
197       { "%jmp/1xz",of_JMP1XZ, 2,  {OA_CODE_PTR, OA_BIT1,     OA_NONE} },
198       { "%join",   of_JOIN,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
199       { "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE,  OA_NONE} },
200       { "%load/ar",of_LOAD_AR,2,  {OA_ARR_PTR,  OA_BIT1,     OA_NONE} },
201       { "%load/dar/r",  of_LOAD_DAR_R,    1, {OA_FUNC_PTR, OA_NONE, OA_NONE}},
202       { "%load/dar/str",of_LOAD_DAR_STR,  1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
203       { "%load/dar/vec4",of_LOAD_DAR_VEC4,1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
204       { "%load/obj",   of_LOAD_OBJ,  1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
205       { "%load/obja",  of_LOAD_OBJA, 2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
206       { "%load/real",  of_LOAD_REAL, 1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
207       { "%load/str",   of_LOAD_STR,  1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
208       { "%load/stra",  of_LOAD_STRA, 2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
209       { "%load/vec4",  of_LOAD_VEC4, 1,{OA_FUNC_PTR,OA_NONE,  OA_NONE} },
210       { "%load/vec4a", of_LOAD_VEC4A,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
211       { "%max/wr", of_MAX_WR, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
212       { "%min/wr", of_MIN_WR, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
213       { "%mod",    of_MOD,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
214       { "%mod/s",  of_MOD_S,  0,  {OA_NONE,     OA_NONE,     OA_NONE} },
215       { "%mod/wr", of_MOD_WR, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
216       { "%mov/wu", of_MOV_WU, 2,  {OA_BIT1,     OA_BIT2,     OA_NONE} },
217       { "%mul",    of_MUL,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
218       { "%mul/wr", of_MUL_WR, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
219       { "%muli",   of_MULI,   3,  {OA_BIT1,     OA_BIT2,     OA_NUMBER} },
220       { "%nand",   of_NAND,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
221       { "%nand/r", of_NANDR,  0,  {OA_NONE,     OA_NONE,     OA_NONE} },
222       { "%new/cobj",  of_NEW_COBJ,  1, {OA_VPI_PTR,OA_NONE,  OA_NONE} },
223       { "%new/darray",of_NEW_DARRAY,2, {OA_BIT1,   OA_STRING,OA_NONE} },
224       { "%noop",   of_NOOP,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
225       { "%nor",    of_NOR,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
226       { "%nor/r",  of_NORR,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
227       { "%null",   of_NULL,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
228       { "%or",     of_OR,     0,  {OA_NONE,     OA_NONE,     OA_NONE} },
229       { "%or/r",   of_ORR,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
230       { "%pad/s",  of_PAD_S,  1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
231       { "%pad/u",  of_PAD_U,  1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
232       { "%part/s", of_PART_S, 1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
233       { "%part/u", of_PART_U, 1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
234       { "%parti/s",of_PARTI_S,3,  {OA_NUMBER,   OA_BIT1,     OA_BIT2} },
235       { "%parti/u",of_PARTI_U,3,  {OA_NUMBER,   OA_BIT1,     OA_BIT2} },
236       { "%pop/obj", of_POP_OBJ, 2, {OA_BIT1,    OA_BIT2,     OA_NONE} },
237       { "%pop/real",of_POP_REAL,1, {OA_NUMBER,  OA_NONE,     OA_NONE} },
238       { "%pop/str", of_POP_STR, 1, {OA_NUMBER,  OA_NONE,     OA_NONE} },
239       { "%pop/vec4",of_POP_VEC4,1, {OA_NUMBER,  OA_NONE,     OA_NONE} },
240       { "%pow",     of_POW,     0,  {OA_NONE,   OA_NONE,     OA_NONE} },
241       { "%pow/s",   of_POW_S,   0,  {OA_NONE,   OA_NONE,     OA_NONE} },
242       { "%pow/wr",  of_POW_WR,  0,  {OA_NONE,   OA_NONE,     OA_NONE} },
243       { "%prop/obj",of_PROP_OBJ,2,  {OA_NUMBER,   OA_BIT1,     OA_NONE} },
244       { "%prop/r",  of_PROP_R,  1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
245       { "%prop/str",of_PROP_STR,1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
246       { "%prop/v",  of_PROP_V,  1,  {OA_NUMBER,   OA_NONE,     OA_NONE} },
247       { "%pushi/real",of_PUSHI_REAL,2,{OA_BIT1,   OA_BIT2,   OA_NONE} },
248       { "%pushi/str", of_PUSHI_STR, 1,{OA_STRING, OA_NONE,   OA_NONE} },
249       { "%pushi/vec4",of_PUSHI_VEC4,3,{OA_BIT1,   OA_BIT2,   OA_NUMBER} },
250       { "%pushv/str", of_PUSHV_STR, 0,{OA_NONE,   OA_NONE,   OA_NONE} },
251       { "%putc/str/vec4",of_PUTC_STR_VEC4,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
252       { "%qinsert/real",of_QINSERT_REAL,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
253       { "%qinsert/str", of_QINSERT_STR, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
254       { "%qinsert/v",   of_QINSERT_V,   3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
255       { "%qpop/b/real",of_QPOP_B_REAL,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
256       { "%qpop/b/str", of_QPOP_B_STR, 1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
257       { "%qpop/b/v",   of_QPOP_B_V,   2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
258       { "%qpop/f/real",of_QPOP_F_REAL,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
259       { "%qpop/f/str", of_QPOP_F_STR, 1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
260       { "%qpop/f/v",   of_QPOP_F_V,   2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
261       { "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
262       { "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
263       { "%release/wr", of_RELEASE_WR, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
264       { "%replicate", of_REPLICATE,   1,{OA_NUMBER,  OA_NONE,OA_NONE} },
265       { "%ret/real",  of_RET_REAL,    1,{OA_NUMBER,  OA_NONE,OA_NONE} },
266       { "%ret/str",   of_RET_STR,     1,{OA_NUMBER,  OA_NONE,OA_NONE} },
267       { "%ret/vec4",  of_RET_VEC4,    3,{OA_NUMBER,  OA_BIT1,OA_BIT2} },
268       { "%retload/real",of_RETLOAD_REAL,1,{OA_NUMBER,  OA_NONE,OA_NONE} },
269       { "%retload/str", of_RETLOAD_STR, 1,{OA_NUMBER,  OA_NONE,OA_NONE} },
270       { "%retload/vec4",of_RETLOAD_VEC4,1,{OA_NUMBER,  OA_NONE,OA_NONE} },
271       { "%scopy",  of_SCOPY,  0,  {OA_NONE,     OA_NONE,     OA_NONE} },
272       { "%set/dar/obj/real",of_SET_DAR_OBJ_REAL,1,{OA_NUMBER,OA_NONE,OA_NONE} },
273       { "%set/dar/obj/str", of_SET_DAR_OBJ_STR, 1,{OA_NUMBER,OA_NONE,OA_NONE} },
274       { "%set/dar/obj/vec4",of_SET_DAR_OBJ_VEC4,1,{OA_NUMBER,OA_NONE,OA_NONE} },
275       { "%shiftl",   of_SHIFTL,   1, {OA_NUMBER, OA_NONE,   OA_NONE} },
276       { "%shiftr",   of_SHIFTR,   1, {OA_NUMBER, OA_NONE,   OA_NONE} },
277       { "%shiftr/s", of_SHIFTR_S, 1, {OA_NUMBER, OA_NONE,   OA_NONE} },
278       { "%split/vec4",    of_SPLIT_VEC4,    1,{OA_NUMBER,   OA_NONE, OA_NONE} },
279       { "%store/dar/r",   of_STORE_DAR_R,   1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
280       { "%store/dar/str", of_STORE_DAR_STR, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
281       { "%store/dar/vec4",of_STORE_DAR_VEC4,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
282       { "%store/obj",   of_STORE_OBJ,   1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
283       { "%store/obja",  of_STORE_OBJA,  2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
284       { "%store/prop/obj",of_STORE_PROP_OBJ,2, {OA_NUMBER,  OA_BIT1, OA_NONE} },
285       { "%store/prop/r",  of_STORE_PROP_R,  1, {OA_NUMBER,  OA_NONE, OA_NONE} },
286       { "%store/prop/str",of_STORE_PROP_STR,1, {OA_NUMBER,  OA_NONE, OA_NONE} },
287       { "%store/prop/v",  of_STORE_PROP_V,  2, {OA_NUMBER,  OA_BIT1, OA_NONE} },
288       { "%store/qb/r",   of_STORE_QB_R,    2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
289       { "%store/qb/str", of_STORE_QB_STR,  2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
290       { "%store/qb/v",   of_STORE_QB_V,    3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
291       { "%store/qdar/r",  of_STORE_QDAR_R,  2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
292       { "%store/qdar/str",of_STORE_QDAR_STR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
293       { "%store/qdar/v",  of_STORE_QDAR_V,  3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
294       { "%store/qf/r",   of_STORE_QF_R,    2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
295       { "%store/qf/str", of_STORE_QF_STR,  2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
296       { "%store/qf/v",   of_STORE_QF_V,    3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
297       { "%store/qobj/r",  of_STORE_QOBJ_R,  2, {OA_FUNC_PTR,OA_BIT1, OA_NONE} },
298       { "%store/qobj/str",of_STORE_QOBJ_STR,2, {OA_FUNC_PTR,OA_BIT1, OA_NONE} },
299       { "%store/qobj/v",  of_STORE_QOBJ_V,  3, {OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
300       { "%store/real",    of_STORE_REAL,    1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
301       { "%store/reala",   of_STORE_REALA,   2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
302       { "%store/str",     of_STORE_STR,     1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
303       { "%store/stra",    of_STORE_STRA,    2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
304       { "%store/vec4",    of_STORE_VEC4,    3, {OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
305       { "%store/vec4a",   of_STORE_VEC4A,   3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
306       { "%sub",    of_SUB,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
307       { "%sub/wr", of_SUB_WR, 0,  {OA_NONE,     OA_NONE,     OA_NONE} },
308       { "%subi",   of_SUBI,   3,  {OA_BIT1,     OA_BIT2,     OA_NUMBER} },
309       { "%substr",     of_SUBSTR,     2,{OA_BIT1,    OA_BIT2, OA_NONE} },
310       { "%substr/vec4",of_SUBSTR_VEC4,2,{OA_BIT1,    OA_BIT2, OA_NONE} },
311       { "%test_nul",     of_TEST_NUL,     1,{OA_FUNC_PTR,OA_NONE,    OA_NONE} },
312       { "%test_nul/a",   of_TEST_NUL_A,   2,{OA_ARR_PTR, OA_BIT1,    OA_NONE} },
313       { "%test_nul/obj", of_TEST_NUL_OBJ, 0,{OA_NONE,    OA_NONE,    OA_NONE} },
314       { "%test_nul/prop",of_TEST_NUL_PROP,2,{OA_NUMBER,  OA_BIT1,    OA_NONE} },
315       { "%wait",   of_WAIT,   1,  {OA_FUNC_PTR, OA_NONE,     OA_NONE} },
316       { "%wait/fork",of_WAIT_FORK,0,{OA_NONE,   OA_NONE,     OA_NONE} },
317       { "%xnor",   of_XNOR,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
318       { "%xnor/r", of_XNORR,  0,  {OA_NONE,     OA_NONE,     OA_NONE} },
319       { "%xor",    of_XOR,    0,  {OA_NONE,     OA_NONE,     OA_NONE} },
320       { "%xor/r",  of_XORR,   0,  {OA_NONE,     OA_NONE,     OA_NONE} },
321       { 0, of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }
322 };
323 
324 static const unsigned opcode_count =
325                     sizeof(opcode_table)/sizeof(*opcode_table) - 1;
326 
opcode_compare(const void * k,const void * r)327 static int opcode_compare(const void*k, const void*r)
328 {
329       const char*kp = (const char*)k;
330       const struct opcode_table_s*rp = (const struct opcode_table_s*)r;
331       return strcmp(kp, rp->mnemonic);
332 }
333 
334 /*
335  * Keep a symbol table of addresses within code space. Labels on
336  * executable opcodes are mapped to their address here.
337  */
338 static symbol_table_t sym_codespace = 0;
339 
340 /*
341  * Keep a symbol table of functors mentioned in the source. This table
342  * is used to resolve references as they come.
343  */
344 static symbol_table_t sym_functors = 0;
345 
346 /*
347  * VPI objects are indexed during compile time so that they can be
348  * linked together as they are created. This symbol table matches
349  * labels to vpiHandles.
350  */
351 static symbol_table_t sym_vpi = 0;
352 
353 
354 /*
355  * If a functor parameter makes a forward reference to a functor, then
356  * I need to save that reference and resolve it after the functors are
357  * created. Use this structure to keep the unresolved references in an
358  * unsorted singly linked list.
359  *
360  * The postpone_functor_input arranges for a functor input to be
361  * resolved and connected at cleanup. This is used if the symbol is
362  * defined after its use in a functor. The ptr parameter is the
363  * complete vvp_input_t for the input port.
364  */
365 
366 
367 /*
368  *  Add a functor to the symbol table
369  */
370 
define_functor_symbol(const char * label,vvp_net_t * net)371 void define_functor_symbol(const char*label, vvp_net_t*net)
372 {
373       symbol_value_t val;
374       val.net = net;
375       sym_set_value(sym_functors, label, val);
376 }
377 
lookup_functor_symbol(const char * label)378 static vvp_net_t*lookup_functor_symbol(const char*label)
379 {
380       assert(sym_functors);
381       symbol_value_t val = sym_get_value(sym_functors, label);
382       return val.net;
383 }
384 
vvp_lookup_handle(const char * label)385 vpiHandle vvp_lookup_handle(const char*label)
386 {
387       symbol_value_t val = sym_get_value(sym_vpi, label);
388       if (val.ptr) return (vpiHandle) val.ptr;
389       return 0;
390 }
391 
vvp_net_lookup(const char * label)392 vvp_net_t* vvp_net_lookup(const char*label)
393 {
394       static bool t0_trigger_generated = false;
395 
396         /* First, look to see if the symbol is a vpi object of some
397 	   sort. If it is, then get the vvp_ipoint_t pointer out of
398 	   the vpiHandle. */
399       symbol_value_t val = sym_get_value(sym_vpi, label);
400       if (val.ptr) {
401 	    vpiHandle vpi = (vpiHandle) val.ptr;
402 	    switch (vpi->get_type_code()) {
403 		case vpiNet:
404 		case vpiReg:
405 		case vpiBitVar:
406 		case vpiByteVar:
407 		case vpiShortIntVar:
408 		case vpiIntVar:
409 		case vpiLongIntVar:
410 		case vpiIntegerVar: {
411 		      __vpiSignal*sig = dynamic_cast<__vpiSignal*>(vpi);
412 		      return sig->node;
413 		}
414 
415 		case vpiRealVar: {
416 		      __vpiRealVar*sig = dynamic_cast<__vpiRealVar*>(vpi);
417 		      return sig->net;
418 		}
419 
420 		case vpiStringVar:
421 		case vpiArrayVar:
422 		case vpiClassVar: {
423 		      __vpiBaseVar*sig = dynamic_cast<__vpiBaseVar*>(vpi);
424 		      return sig->get_net();
425 		}
426 
427 		case vpiNamedEvent: {
428 		      __vpiNamedEvent*tmp = dynamic_cast<__vpiNamedEvent*>(vpi);
429 		      return tmp->funct;
430 		}
431 
432 		default:
433 		  fprintf(stderr, "Unsupported type %d.\n",
434 		          vpi->get_type_code());
435 		  assert(0);
436 	    }
437       }
438 
439 
440 	/* Failing that, look for a general functor. */
441       vvp_net_t*tmp = lookup_functor_symbol(label);
442 
443 	// This is a special label used to create a T0 trigger for the
444 	// always_comb/latch processes.
445      if (! t0_trigger_generated && (strcmp(label, "E_0x0") == 0)) {
446 	      // This should never happen, but if it does then the E_0x0
447 	      // event generation may need to be explicitly generated in
448 	      // the compiler output instead of implicitly in this code.
449 	    assert(! vpip_peek_current_scope()->is_automatic());
450 	    t0_trigger_generated = true;
451 	      // Create a local event with no name for the T0 trigger
452 	    compile_named_event(strdup(label), strcpy(new char [1],""), true);
453 	    tmp = vvp_net_lookup(label);
454 	    assert(tmp);
455 	      // Create a trigger for the T0 event.
456 	    vvp_net_ptr_t ptr (tmp, 0);
457 	    schedule_t0_trigger(ptr);
458      }
459 
460       return tmp;
461 }
462 
463 /*
464  * The resolv_list_s is the base class for a symbol resolve action, and
465  * the resolv_list is an unordered list of these resolve actions. Some
466  * function creates an instance of a resolv_list_s object that
467  * contains the data pertinent to that resolution request, and
468  * executes it with the resolv_submit function. If the operation can
469  * complete, then the resolv_submit deletes the object. Otherwise, it
470  * pushes it onto the resolv_list for later processing.
471  *
472  * Derived classes implement the resolve function to perform the
473  * actual binding or resolution that the instance requires. If the
474  * function succeeds, the resolve method returns true and the object
475  * can be deleted any time.
476  *
477  * The mes parameter of the resolve method tells the resolver that
478  * this call is its last chance. If it cannot complete the operation,
479  * it must print an error message and return false.
480  */
481 static resolv_list_s*resolv_list = 0;
482 
~resolv_list_s()483 resolv_list_s::~resolv_list_s()
484 {
485       free(label_);
486 }
487 
resolv_submit(resolv_list_s * cur)488 void resolv_submit(resolv_list_s*cur)
489 {
490       if (cur->resolve()) {
491 	    delete cur;
492 	    return;
493       }
494 
495       cur->next = resolv_list;
496       resolv_list = cur;
497 }
498 
499 
500 /*
501  * Look up vvp_nets in the symbol table. The "source" is the label for
502  * the net that I want to feed, and net->port[port] is the vvp_net
503  * input that I want that node to feed into. When the name is found,
504  * put net->port[port] into the fan-out list for that node.
505  */
506 struct vvp_net_resolv_list_s: public resolv_list_s {
507 
vvp_net_resolv_list_svvp_net_resolv_list_s508       explicit vvp_net_resolv_list_s(char*l) : resolv_list_s(l) { }
509 	// port to be driven by the located node.
510       vvp_net_ptr_t port;
511       virtual bool resolve(bool mes);
512 };
513 
resolve(bool mes)514 bool vvp_net_resolv_list_s::resolve(bool mes)
515 {
516       vvp_net_t*tmp = vvp_net_lookup(label());
517 
518       if (tmp) {
519 	      // Link the input port to the located output.
520 	    tmp->link(port);
521 	    return true;
522       }
523 
524       if (mes)
525 	    fprintf(stderr, "unresolved vvp_net reference: %s\n", label());
526 
527       return false;
528 }
529 
530 inline static
postpone_functor_input(vvp_net_ptr_t port,char * lab)531 void postpone_functor_input(vvp_net_ptr_t port, char*lab)
532 {
533       struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s(lab);
534       res->port   = port;
535 
536       resolv_submit(res);
537 }
538 
539 
540 /*
541  *  Generic functor reference lookup.
542  */
543 
544 struct functor_gen_resolv_list_s: public resolv_list_s {
functor_gen_resolv_list_sfunctor_gen_resolv_list_s545       explicit functor_gen_resolv_list_s(char*txt) : resolv_list_s(txt) {
546 	    ref = 0;
547       }
548       vvp_net_t**ref;
549       virtual bool resolve(bool mes);
550 };
551 
resolve(bool mes)552 bool functor_gen_resolv_list_s::resolve(bool mes)
553 {
554       vvp_net_t*tmp = vvp_net_lookup(label());
555 
556       if (tmp) {
557 	    *ref = tmp;
558 	    return true;
559       }
560 
561       if (mes)
562 	    fprintf(stderr, "unresolved functor reference: %s\n", label());
563 
564       return false;
565 }
566 
functor_ref_lookup(vvp_net_t ** ref,char * lab)567 void functor_ref_lookup(vvp_net_t**ref, char*lab)
568 {
569       struct functor_gen_resolv_list_s*res =
570 	    new struct functor_gen_resolv_list_s(lab);
571 
572       res->ref    = ref;
573 
574       resolv_submit(res);
575 }
576 
577 /*
578  *  vpiHandle lookup
579  */
580 
581 struct vpi_handle_resolv_list_s: public resolv_list_s {
vpi_handle_resolv_list_svpi_handle_resolv_list_s582       explicit vpi_handle_resolv_list_s(char*lab) : resolv_list_s(lab) {
583 	    handle = NULL;
584       }
585       virtual bool resolve(bool mes);
586       vpiHandle *handle;
587 };
588 
resolve(bool mes)589 bool vpi_handle_resolv_list_s::resolve(bool mes)
590 {
591       symbol_value_t val = sym_get_value(sym_vpi, label());
592       if (!val.ptr) {
593 	    // check for thread access symbols
594 	    unsigned base, wid;
595 	    size_t n = 0;
596 	    char ss[32];
597 	    if (2 == sscanf(label(), "W<%u,%[r]>%zn", &base, ss, &n)
598 		       && n == strlen(label())) {
599 
600 		  val.ptr = vpip_make_vthr_word(base, ss);
601 		  sym_set_value(sym_vpi, label(), val);
602 
603 	    } else if (1 == sscanf(label(), "S<%u,str>%zn", &base, &n)
604 		       && n == strlen(label())) {
605 
606 		  val.ptr = vpip_make_vthr_str_stack(base);
607 		  sym_set_value(sym_vpi, label(), val);
608 
609 	    } else if (3 == sscanf(label(), "S<%u,vec4,%[su]%u>%zn", &base, ss, &wid, &n)
610 		       && n == strlen(label())) {
611 
612 		  bool signed_flag = false;
613 		  for (char*fp = ss ;  *fp ;  fp += 1) switch (*fp) {
614 		      case 's':
615 			signed_flag = true;
616 			break;
617 		      case 'u':
618 			signed_flag = false;
619 			break;
620 		      default:
621 			break;
622 		  }
623 		  val.ptr = vpip_make_vthr_vec4_stack(base, signed_flag, wid);
624 		  sym_set_value(sym_vpi, label(), val);
625 	    }
626 
627       }
628 
629       if (!val.ptr) {
630 	    // check for memory word  M<mem,base,wid>
631       }
632 
633       if (val.ptr) {
634 	    *handle = (vpiHandle) val.ptr;
635 	    return true;
636       }
637 
638       if (mes)
639 	    fprintf(stderr, "unresolved vpi name lookup: %s\n", label());
640 
641       return false;
642 }
643 
compile_vpi_lookup(vpiHandle * handle,char * label)644 void compile_vpi_lookup(vpiHandle *handle, char*label)
645 {
646       if (strcmp(label, "$time") == 0) {
647 	    *handle = vpip_sim_time(vpip_peek_current_scope(), false);
648 	    free(label);
649 	    return;
650       }
651 
652       if (strcmp(label, "$stime") == 0) {
653 	    *handle = vpip_sim_time(vpip_peek_current_scope(), true);
654 	    free(label);
655 	    return;
656       }
657 
658       if (strcmp(label, "$realtime") == 0) {
659 	    *handle = vpip_sim_realtime(vpip_peek_current_scope());
660 	    free(label);
661 	    return;
662       }
663 
664       if (strcmp(label, "$simtime") == 0) {
665 	    *handle = vpip_sim_time(0, false);
666 	    free(label);
667 	    return;
668       }
669 
670       struct vpi_handle_resolv_list_s*res
671 	    = new struct vpi_handle_resolv_list_s(label);
672 
673       res->handle = handle;
674       resolv_submit(res);
675 }
676 
677 /*
678  * Code Label lookup
679  */
680 
681 struct code_label_resolv_list_s: public resolv_list_s {
code_label_resolv_list_scode_label_resolv_list_s682       explicit code_label_resolv_list_s(char*lab, bool cptr2) : resolv_list_s(lab) {
683 	    code = NULL;
684 	    cptr2_flag = cptr2;
685       }
686       struct vvp_code_s *code;
687       bool cptr2_flag;
688       virtual bool resolve(bool mes);
689 };
690 
resolve(bool mes)691 bool code_label_resolv_list_s::resolve(bool mes)
692 {
693       symbol_value_t val = sym_get_value(sym_codespace, label());
694       if (val.ptr) {
695 	    if (cptr2_flag)
696 		  code->cptr2 = reinterpret_cast<vvp_code_t>(val.ptr);
697 	    else
698 		  code->cptr = reinterpret_cast<vvp_code_t>(val.ptr);
699 	    return true;
700       }
701 
702       if (mes)
703 	    fprintf(stderr, "unresolved code label: %s\n", label());
704 
705       return false;
706 }
707 
code_label_lookup(struct vvp_code_s * code,char * label,bool cptr2)708 void code_label_lookup(struct vvp_code_s *code, char *label, bool cptr2)
709 {
710       struct code_label_resolv_list_s *res
711 	    = new struct code_label_resolv_list_s(label, cptr2);
712 
713       res->code  = code;
714 
715       resolv_submit(res);
716 }
717 
718 struct code_array_resolv_list_s: public resolv_list_s {
code_array_resolv_list_scode_array_resolv_list_s719       explicit code_array_resolv_list_s(char*lab) : resolv_list_s(lab) {
720 	    code = NULL;
721       }
722       struct vvp_code_s *code;
723       virtual bool resolve(bool mes);
724 };
725 
resolve(bool mes)726 bool code_array_resolv_list_s::resolve(bool mes)
727 {
728       code->array = array_find(label());
729       if (code->array != 0) {
730 	    return true;
731       }
732 
733       if (mes)
734 	    fprintf(stderr, "Array unresolved: %s\n", label());
735 
736       return false;
737 }
738 
compile_array_lookup(struct vvp_code_s * code,char * label)739 static void compile_array_lookup(struct vvp_code_s*code, char*label)
740 {
741       struct code_array_resolv_list_s *res
742 	    = new struct code_array_resolv_list_s(label);
743 
744       res->code  = code;
745 
746       resolv_submit(res);
747 }
748 
749 static std::list<struct __vpiSysTaskCall*> scheduled_compiletf;
750 
compile_compiletf(struct __vpiSysTaskCall * obj)751 void compile_compiletf(struct __vpiSysTaskCall*obj)
752 {
753       if (obj->defn->info.compiletf == 0)
754 	    return;
755 
756       scheduled_compiletf.push_back(obj);
757 }
758 
759 /*
760  * When parsing is otherwise complete, this function is called to do
761  * the final stuff. Clean up deferred linking here.
762  */
763 
compile_cleanup(void)764 void compile_cleanup(void)
765 {
766       int lnerrs = -1;
767       int nerrs = 0;
768       int last;
769 
770       if (verbose_flag) {
771 	    fprintf(stderr, " ... Linking\n");
772 	    fflush(stderr);
773       }
774 
775       do {
776 	    resolv_list_s *res = resolv_list;
777 	    resolv_list = 0x0;
778 	    last = nerrs == lnerrs;
779 	    lnerrs = nerrs;
780 	    nerrs = 0;
781 	    while (res) {
782 		  resolv_list_s *cur = res;
783 		  res = res->next;
784 		  if (cur->resolve(last))
785 			delete cur;
786 		  else {
787 			nerrs++;
788 			cur->next = resolv_list;
789 			resolv_list = cur;
790 		  }
791 	    }
792 	    if (nerrs && last)
793 		  fprintf(stderr,
794 			  "compile_cleanup: %d unresolved items\n",
795 			  nerrs);
796       } while (nerrs && !last);
797 
798       compile_errors += nerrs;
799 
800       if (verbose_flag) {
801 	    fprintf(stderr, " ... Removing symbol tables\n");
802 	    fflush(stderr);
803       }
804 
805 	/* After compile is complete, the vpi symbol table is no
806 	   longer needed. VPI objects are located by following
807 	   scopes. */
808       delete_symbol_table(sym_vpi);
809       sym_vpi = 0;
810 
811 	/* Don't need the code labels. The instructions have numeric
812 	   pointers in them, the symbol table is no longer needed. */
813       delete_symbol_table(sym_codespace);
814       sym_codespace = 0;
815 
816       delete_symbol_table(sym_functors);
817       sym_functors = 0;
818 
819       delete_udp_symbols();
820 
821       compile_island_cleanup();
822       compile_array_cleanup();
823 
824       if (verbose_flag) {
825 	    fprintf(stderr, " ... Compiletf functions\n");
826 	    fflush(stderr);
827       }
828 
829       assert(vpi_mode_flag == VPI_MODE_NONE);
830       vpi_mode_flag = VPI_MODE_COMPILETF;
831 
832       while (! scheduled_compiletf.empty()) {
833 	    struct __vpiSysTaskCall*obj = scheduled_compiletf.front();
834 	    scheduled_compiletf.pop_front();
835 	    vpip_cur_task = obj;
836 	    obj->defn->info.compiletf (obj->defn->info.user_data);
837 	    vpip_cur_task = 0;
838       }
839 
840       vpi_mode_flag = VPI_MODE_NONE;
841 }
842 
compile_vpi_symbol(const char * label,vpiHandle obj)843 void compile_vpi_symbol(const char*label, vpiHandle obj)
844 {
845       symbol_value_t val;
846       val.ptr = obj;
847       sym_set_value(sym_vpi, label, val);
848 }
849 
850 /*
851  * Initialize the compiler by allocation empty symbol tables and
852  * initializing the various address spaces.
853  */
compile_init(void)854 void compile_init(void)
855 {
856       sym_vpi = new_symbol_table();
857 
858       sym_functors = new_symbol_table();
859 
860       sym_codespace = new_symbol_table();
861       codespace_init();
862 }
863 
compile_load_vpi_module(char * name)864 void compile_load_vpi_module(char*name)
865 {
866       vpip_load_module(name);
867       delete[] name;
868 }
869 
compile_vpi_time_precision(long pre)870 void compile_vpi_time_precision(long pre)
871 {
872       vpip_set_time_precision(pre);
873 }
874 
875 /*
876  * Convert a Cr string value to double.
877  *
878  * The format is broken into mantissa and exponent.
879  * The exponent in turn includes a sign bit.
880  *
881  * The mantissa is a 64bit integer value (encoded in hex).
882  *
883  * The exponent included the sign bit (0x4000) and the binary
884  * exponent offset by 0x1000. The actual exponent is the
885  * encoded exponent - 0x1000.
886  *
887  * The real value is sign * (mant ** exp).
888  */
crstring_test(const char * str)889 bool crstring_test(const char*str)
890 {
891       if (strncmp(str, "Cr<", 3) != 0) return false;
892       const char*tp = strchr(str, '>');
893       if (tp == 0) return false;
894       if (tp[1] != 0) return false;
895 
896       if ((strspn(str+3, "0123456789abcdefmg")+3) != (size_t)(tp - str))
897 	  return false;
898 
899       return true;
900 }
901 
crstring_to_double(const char * label)902 double crstring_to_double(const char*label)
903 {
904       const char*cp = label+3;
905       assert(*cp == 'm');
906       cp += 1;
907       char*ep;
908       uint64_t mant = strtoull(cp, &ep, 16);
909       cp = ep;
910       assert(*cp == 'g');
911       cp += 1;
912       int exp = strtoul(cp, 0, 16);
913 
914       double tmp;
915       if (mant == 0 && exp == 0x3fff) {
916 	    tmp = INFINITY;
917       } else if (mant == 0 && exp == 0x7fff) {
918 	    tmp = -INFINITY;
919       } else if (exp == 0x3fff) {
920 	    tmp = nan("");
921       } else {
922 	    double sign = (exp & 0x4000)? -1.0 : 1.0;
923 	    exp &= 0x1fff;
924 
925 	    tmp = sign * ldexp((double)mant, exp - 0x1000);
926       }
927 
928       return tmp;
929 }
930 
931 /*
932  * Run through the arguments looking for the nodes that are
933  * connected to my input ports. For each source functor that I
934  * find, connect the output of that functor to the indexed
935  * input by inserting myself (complete with the port number in
936  * the vvp_ipoint_t) into the list that the source heads.
937  *
938  * If the source functor is not declared yet, then don't do
939  * the link yet. Save the reference to be resolved later.
940  *
941  * If the source is a constant value, then set the ival of the functor
942  * and skip the symbol lookup.
943  */
944 
input_connect(vvp_net_t * fdx,unsigned port,char * label)945 void input_connect(vvp_net_t*fdx, unsigned port, char*label)
946 {
947       vvp_net_ptr_t ifdx = vvp_net_ptr_t(fdx, port);
948 
949 	/* Is this a vvp_vector4_t constant value? */
950       if (c4string_test(label)) {
951 
952 	    vvp_vector4_t tmp = c4string_to_vector4(label);
953 
954 	      // Inputs that are constants are schedule to execute as
955 	      // soon at the simulation starts. In Verilog, constants
956 	      // start propagating when the simulation starts, just
957 	      // like any other signal value. But letting the
958 	      // scheduler distribute the constant value has the
959 	      // additional advantage that the constant is not
960 	      // propagated until the network is fully linked.
961 	    schedule_set_vector(ifdx, tmp);
962 
963 	    free(label);
964 	    return;
965       }
966 
967 	/* Is this a vvp_vector8_t constant value? */
968       if (c8string_test(label)) {
969 
970 	    vvp_vector8_t tmp = c8string_to_vector8(label);
971 	    schedule_set_vector(ifdx, tmp);
972 
973 	    free(label);
974 	    return;
975       }
976 
977 	/* Handle the Cr<> constant driver, which is a real-value
978 	   driver. */
979       if (crstring_test(label)) {
980 
981 	    double tmp = crstring_to_double(label);
982 
983 	    schedule_set_vector(ifdx, tmp);
984 	    free(label);
985 	    return;
986       }
987 
988 	/* Handle the general case that this is a label for a node in
989 	   the vvp net. This arranges for the label to be preserved in
990 	   a linker list, and linked when the symbol table is
991 	   complete. */
992       postpone_functor_input(ifdx, label);
993 }
994 
inputs_connect(vvp_net_t * fdx,unsigned argc,struct symb_s * argv)995 void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv)
996 {
997       if (argc > 4) {
998 	    std::cerr << "XXXX argv[0] = " << argv[0].text << std::endl;
999       }
1000       assert(argc <= 4);
1001 
1002       for (unsigned idx = 0;  idx < argc;  idx += 1) {
1003 
1004 	    input_connect(fdx, idx, argv[idx].text);
1005       }
1006 }
1007 
wide_inputs_connect(vvp_wide_fun_core * core,unsigned argc,struct symb_s * argv)1008 void wide_inputs_connect(vvp_wide_fun_core*core,
1009 			 unsigned argc, struct symb_s*argv)
1010 {
1011 	/* Create input functors to receive values from the
1012 	   network. These functors pass the data to the core. */
1013       unsigned input_functors = (argc+3) / 4;
1014       for (unsigned idx = 0 ;  idx < input_functors ;  idx += 1) {
1015 	    unsigned base = idx*4;
1016 	    unsigned trans = 4;
1017 	    if (base+trans > argc)
1018 		  trans = argc - base;
1019 
1020 	    vvp_wide_fun_t*cur = new vvp_wide_fun_t(core, base);
1021 	    vvp_net_t*ptr = new vvp_net_t;
1022 	    ptr->fun = cur;
1023 
1024 	    inputs_connect(ptr, trans, argv+base);
1025       }
1026 }
1027 
make_arith(T_ * arith,char * label,unsigned argc,struct symb_s * argv)1028 template <class T_> void make_arith(T_ *arith, char*label,
1029 				    unsigned argc, struct symb_s*argv)
1030 {
1031       vvp_net_t* ptr = new vvp_net_t;
1032       ptr->fun = arith;
1033 
1034       define_functor_symbol(label, ptr);
1035       free(label);
1036 
1037       assert(argc == 2);
1038       inputs_connect(ptr, argc, argv);
1039 
1040       free(argv);
1041 }
1042 
compile_arith_cast_int(char * label,long width,unsigned argc,struct symb_s * argv)1043 void compile_arith_cast_int(char*label, long width,
1044                             unsigned argc, struct symb_s*argv)
1045 {
1046       vvp_arith_cast_int*arith = new vvp_arith_cast_int((unsigned) width);
1047 
1048       vvp_net_t* ptr = new vvp_net_t;
1049       ptr->fun = arith;
1050 
1051       define_functor_symbol(label, ptr);
1052       free(label);
1053 
1054       assert(argc == 1);
1055       inputs_connect(ptr, argc, argv);
1056       free(argv);
1057 }
1058 
compile_arith_cast_vec2(char * label,long width,unsigned argc,struct symb_s * argv)1059 void compile_arith_cast_vec2(char*label, long width,
1060 			     unsigned argc, struct symb_s*argv)
1061 {
1062       vvp_arith_cast_vec2*arith = new vvp_arith_cast_vec2((unsigned) width);
1063 
1064       vvp_net_t* ptr = new vvp_net_t;
1065       ptr->fun = arith;
1066 
1067       define_functor_symbol(label, ptr);
1068       free(label);
1069 
1070       assert(argc == 1);
1071       inputs_connect(ptr, argc, argv);
1072       free(argv);
1073 }
1074 
compile_arith_cast_real(char * label,bool signed_flag,unsigned argc,struct symb_s * argv)1075 void compile_arith_cast_real(char*label, bool signed_flag,
1076                              unsigned argc, struct symb_s*argv)
1077 {
1078       vvp_arith_cast_real*arith = new vvp_arith_cast_real(signed_flag);
1079 
1080       vvp_net_t* ptr = new vvp_net_t;
1081       ptr->fun = arith;
1082 
1083       define_functor_symbol(label, ptr);
1084       free(label);
1085 
1086       assert(argc == 1);
1087       inputs_connect(ptr, argc, argv);
1088       free(argv);
1089 }
1090 
compile_arith_abs(char * label,unsigned argc,struct symb_s * argv)1091 void compile_arith_abs(char*label, unsigned argc, struct symb_s*argv)
1092 {
1093       vvp_arith_abs*arith = new vvp_arith_abs;
1094 
1095       vvp_net_t* ptr = new vvp_net_t;
1096       ptr->fun = arith;
1097 
1098       define_functor_symbol(label, ptr);
1099       free(label);
1100 
1101       assert(argc == 1);
1102       inputs_connect(ptr, argc, argv);
1103       free(argv);
1104 }
1105 
compile_arith_div(char * label,long wid,bool signed_flag,unsigned argc,struct symb_s * argv)1106 void compile_arith_div(char*label, long wid, bool signed_flag,
1107 		       unsigned argc, struct symb_s*argv)
1108 {
1109       assert( wid > 0 );
1110 
1111       if (argc != 2) {
1112 	    const char *suffix = "";
1113 	    if (signed_flag) suffix = ".s";
1114 	    fprintf(stderr, "%s; .arith/div%s has wrong number of "
1115 	                    "symbols\n", label, suffix);
1116 	    compile_errors += 1;
1117 	    return;
1118       }
1119 
1120       vvp_arith_ *arith = new vvp_arith_div(wid, signed_flag);
1121       make_arith(arith, label, argc, argv);
1122 }
1123 
compile_arith_div_r(char * label,unsigned argc,struct symb_s * argv)1124 void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv)
1125 {
1126       if (argc != 2) {
1127 	    fprintf(stderr, "%s; .arith/divr has wrong number of symbols\n", label);
1128 	    compile_errors += 1;
1129 	    return;
1130       }
1131 
1132       vvp_arith_real_ *arith = new vvp_arith_div_real;
1133       make_arith(arith, label, argc, argv);
1134 }
1135 
compile_arith_mod(char * label,long wid,bool signed_flag,unsigned argc,struct symb_s * argv)1136 void compile_arith_mod(char*label, long wid, bool signed_flag,
1137 		       unsigned argc, struct symb_s*argv)
1138 {
1139       assert( wid > 0 );
1140 
1141       if (argc != 2) {
1142 	    fprintf(stderr, "%s .arith/mod has wrong number of symbols\n", label);
1143 	    compile_errors += 1;
1144 	    return;
1145       }
1146 
1147       vvp_arith_ *arith = new vvp_arith_mod(wid, signed_flag);
1148 
1149       make_arith(arith, label, argc, argv);
1150 }
1151 
compile_arith_mod_r(char * label,unsigned argc,struct symb_s * argv)1152 void compile_arith_mod_r(char*label, unsigned argc, struct symb_s*argv)
1153 {
1154       if (argc != 2) {
1155 	    fprintf(stderr, "%s .arith/mod.r has wrong number of symbols\n", label);
1156 	    compile_errors += 1;
1157 	    return;
1158       }
1159 
1160       vvp_arith_real_ *arith = new vvp_arith_mod_real;
1161       make_arith(arith, label, argc, argv);
1162 }
1163 
compile_arith_mult(char * label,long wid,unsigned argc,struct symb_s * argv)1164 void compile_arith_mult(char*label, long wid,
1165 			unsigned argc, struct symb_s*argv)
1166 {
1167       assert( wid > 0 );
1168 
1169       if (argc != 2) {
1170 	    fprintf(stderr, "%s .arith/mult has wrong number of symbols\n", label);
1171 	    compile_errors += 1;
1172 	    return;
1173       }
1174 
1175       vvp_arith_ *arith = new vvp_arith_mult(wid);
1176       make_arith(arith, label, argc, argv);
1177 }
1178 
compile_arith_mult_r(char * label,unsigned argc,struct symb_s * argv)1179 void compile_arith_mult_r(char*label, unsigned argc, struct symb_s*argv)
1180 {
1181       if (argc != 2) {
1182 	    fprintf(stderr, "%s .arith/mult.r has wrong number of symbols\n", label);
1183 	    compile_errors += 1;
1184 	    return;
1185       }
1186 
1187       vvp_arith_real_ *arith = new vvp_arith_mult_real;
1188       make_arith(arith, label, argc, argv);
1189 }
1190 
1191 
compile_arith_pow(char * label,long wid,bool signed_flag,unsigned argc,struct symb_s * argv)1192 void compile_arith_pow(char*label, long wid, bool signed_flag,
1193 		       unsigned argc, struct symb_s*argv)
1194 {
1195       assert( wid > 0 );
1196 
1197       if (argc != 2) {
1198 	    const char *suffix = "";
1199 	    if (signed_flag) suffix = ".s";
1200 	    fprintf(stderr, "%s .arith/pow%s has wrong number of "
1201 	                    "symbols\n", label, suffix);
1202 	    compile_errors += 1;
1203 	    return;
1204       }
1205 
1206       vvp_arith_ *arith = new vvp_arith_pow(wid, signed_flag);
1207       make_arith(arith, label, argc, argv);
1208 }
1209 
compile_arith_pow_r(char * label,unsigned argc,struct symb_s * argv)1210 void compile_arith_pow_r(char*label, unsigned argc, struct symb_s*argv)
1211 {
1212       if (argc != 2) {
1213 	    fprintf(stderr, "%s .arith/pow.r has wrong number of symbols\n", label);
1214 	    compile_errors += 1;
1215 	    return;
1216       }
1217 
1218       vvp_arith_real_ *arith = new vvp_arith_pow_real;
1219       make_arith(arith, label, argc, argv);
1220 }
1221 
compile_arith_sub(char * label,long wid,unsigned argc,struct symb_s * argv)1222 void compile_arith_sub(char*label, long wid, unsigned argc, struct symb_s*argv)
1223 {
1224       assert( wid > 0 );
1225 
1226       if (argc != 2) {
1227 	    fprintf(stderr, "%s .arith/sub has wrong number of symbols\n", label);
1228 	    compile_errors += 1;
1229 	    return;
1230       }
1231 
1232       vvp_arith_ *arith = new vvp_arith_sub(wid);
1233       make_arith(arith, label, argc, argv);
1234 }
1235 
compile_arith_sub_r(char * label,unsigned argc,struct symb_s * argv)1236 void compile_arith_sub_r(char*label, unsigned argc, struct symb_s*argv)
1237 {
1238       if (argc != 2) {
1239 	    fprintf(stderr, "%s; .arith/sub.r has wrong number of symbols\n", label);
1240 	    compile_errors += 1;
1241 	    return;
1242       }
1243 
1244       vvp_arith_real_ *arith = new vvp_arith_sub_real;
1245       make_arith(arith, label, argc, argv);
1246 }
1247 
compile_arith_sum(char * label,long wid,unsigned argc,struct symb_s * argv)1248 void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
1249 {
1250       assert( wid > 0 );
1251 
1252       if (argc != 2) {
1253 	    fprintf(stderr, "%s .arith/sum has wrong number of symbols\n", label);
1254 	    compile_errors += 1;
1255 	    return;
1256       }
1257 
1258       vvp_arith_ *arith = new vvp_arith_sum(wid);
1259       make_arith(arith, label, argc, argv);
1260 }
1261 
compile_arith_sum_r(char * label,unsigned argc,struct symb_s * argv)1262 void compile_arith_sum_r(char*label, unsigned argc, struct symb_s*argv)
1263 {
1264       if (argc != 2) {
1265 	    fprintf(stderr, "%s .arith/sum.r has wrong number of symbols\n", label);
1266 	    compile_errors += 1;
1267 	    return;
1268       }
1269 
1270       vvp_arith_real_ *arith = new vvp_arith_sum_real;
1271       make_arith(arith, label, argc, argv);
1272 }
1273 
compile_cmp_eeq(char * label,long wid,unsigned argc,struct symb_s * argv)1274 void compile_cmp_eeq(char*label, long wid,
1275 		     unsigned argc, struct symb_s*argv)
1276 {
1277       assert( wid > 0 );
1278 
1279       if (argc != 2) {
1280 	    fprintf(stderr, "%s .cmp/eeq has wrong number of symbols\n",label);
1281 	    compile_errors += 1;
1282 	    return;
1283       }
1284 
1285       vvp_arith_ *arith = new vvp_cmp_eeq(wid);
1286 
1287       make_arith(arith, label, argc, argv);
1288 }
1289 
compile_cmp_nee(char * label,long wid,unsigned argc,struct symb_s * argv)1290 void compile_cmp_nee(char*label, long wid,
1291 		     unsigned argc, struct symb_s*argv)
1292 {
1293       assert( wid > 0 );
1294 
1295       if (argc != 2) {
1296 	    fprintf(stderr, "%s .cmp/eeq has wrong number of symbols\n",label);
1297 	    compile_errors += 1;
1298 	    return;
1299       }
1300 
1301       vvp_arith_ *arith = new vvp_cmp_nee(wid);
1302 
1303       make_arith(arith, label, argc, argv);
1304 }
1305 
compile_cmp_eq(char * label,long wid,unsigned argc,struct symb_s * argv)1306 void compile_cmp_eq(char*label, long wid, unsigned argc, struct symb_s*argv)
1307 {
1308       assert( wid > 0 );
1309 
1310       if (argc != 2) {
1311 	    fprintf(stderr, "%s .cmp/eq has wrong number of symbols\n",label);
1312 	    compile_errors += 1;
1313 	    return;
1314       }
1315 
1316       vvp_arith_ *arith = new vvp_cmp_eq(wid);
1317       make_arith(arith, label, argc, argv);
1318 }
1319 
compile_cmp_eqx(char * label,long wid,unsigned argc,struct symb_s * argv)1320 void compile_cmp_eqx(char*label, long wid, unsigned argc, struct symb_s*argv)
1321 {
1322       assert( wid > 0 );
1323 
1324       if (argc != 2) {
1325 	    fprintf(stderr, "%s .cmp/eqx has wrong number of symbols\n",label);
1326 	    compile_errors += 1;
1327 	    return;
1328       }
1329 
1330       vvp_arith_ *arith = new vvp_cmp_eqx(wid);
1331       make_arith(arith, label, argc, argv);
1332 }
1333 
compile_cmp_eqz(char * label,long wid,unsigned argc,struct symb_s * argv)1334 void compile_cmp_eqz(char*label, long wid, unsigned argc, struct symb_s*argv)
1335 {
1336       assert( wid > 0 );
1337 
1338       if (argc != 2) {
1339 	    fprintf(stderr, "%s .cmp/eqz has wrong number of symbols\n",label);
1340 	    compile_errors += 1;
1341 	    return;
1342       }
1343 
1344       vvp_arith_ *arith = new vvp_cmp_eqz(wid);
1345       make_arith(arith, label, argc, argv);
1346 }
1347 
compile_cmp_eq_r(char * label,unsigned argc,struct symb_s * argv)1348 void compile_cmp_eq_r(char*label, unsigned argc, struct symb_s*argv)
1349 {
1350       if (argc != 2) {
1351 	    fprintf(stderr, "%s .cmp/eq.r has wrong number of symbols\n",label);
1352 	    compile_errors += 1;
1353 	    return;
1354       }
1355 
1356       vvp_arith_real_ *arith = new vvp_cmp_eq_real;
1357       make_arith(arith, label, argc, argv);
1358 }
1359 
compile_cmp_ne(char * label,long wid,unsigned argc,struct symb_s * argv)1360 void compile_cmp_ne(char*label, long wid, unsigned argc, struct symb_s*argv)
1361 {
1362       assert( wid > 0 );
1363 
1364       if (argc != 2) {
1365 	    fprintf(stderr, "%s .cmp/ne has wrong number of symbols\n",label);
1366 	    compile_errors += 1;
1367 	    return;
1368       }
1369 
1370       vvp_arith_ *arith = new vvp_cmp_ne(wid);
1371       make_arith(arith, label, argc, argv);
1372 }
1373 
compile_cmp_ne_r(char * label,unsigned argc,struct symb_s * argv)1374 void compile_cmp_ne_r(char*label, unsigned argc, struct symb_s*argv)
1375 {
1376       if (argc != 2) {
1377 	    fprintf(stderr, "%s .cmp/ne.r has wrong number of symbols\n",label);
1378 	    compile_errors += 1;
1379 	    return;
1380       }
1381 
1382       vvp_arith_real_ *arith = new vvp_cmp_ne_real;
1383       make_arith(arith, label, argc, argv);
1384 }
1385 
compile_cmp_ge(char * label,long wid,bool signed_flag,unsigned argc,struct symb_s * argv)1386 void compile_cmp_ge(char*label, long wid, bool signed_flag,
1387 		    unsigned argc, struct symb_s*argv)
1388 {
1389       assert( wid > 0 );
1390 
1391       if (argc != 2) {
1392 	    fprintf(stderr, "%s .cmp/ge has wrong number of symbols\n", label);
1393 	    compile_errors += 1;
1394 	    return;
1395       }
1396 
1397       vvp_arith_ *arith = new vvp_cmp_ge(wid, signed_flag);
1398 
1399       make_arith(arith, label, argc, argv);
1400 }
1401 
compile_cmp_ge_r(char * label,unsigned argc,struct symb_s * argv)1402 void compile_cmp_ge_r(char*label, unsigned argc, struct symb_s*argv)
1403 {
1404       if (argc != 2) {
1405 	    fprintf(stderr, "%s .cmp/ge.r has wrong number of symbols\n",label);
1406 	    compile_errors += 1;
1407 	    return;
1408       }
1409 
1410       vvp_arith_real_ *arith = new vvp_cmp_ge_real;
1411       make_arith(arith, label, argc, argv);
1412 }
1413 
compile_cmp_gt(char * label,long wid,bool signed_flag,unsigned argc,struct symb_s * argv)1414 void compile_cmp_gt(char*label, long wid, bool signed_flag,
1415 		    unsigned argc, struct symb_s*argv)
1416 {
1417       assert( wid > 0 );
1418 
1419       if (argc != 2) {
1420 	    fprintf(stderr, "%s .cmp/gt has wrong number of symbols\n", label);
1421 	    compile_errors += 1;
1422 	    return;
1423       }
1424 
1425       vvp_arith_ *arith = new vvp_cmp_gt(wid, signed_flag);
1426 
1427       make_arith(arith, label, argc, argv);
1428 }
1429 
compile_cmp_gt_r(char * label,unsigned argc,struct symb_s * argv)1430 void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv)
1431 {
1432       if (argc != 2) {
1433 	    fprintf(stderr, "%s .cmp/gt.r has wrong number of symbols\n",label);
1434 	    compile_errors += 1;
1435 	    return;
1436       }
1437 
1438       vvp_arith_real_ *arith = new vvp_cmp_gt_real;
1439       make_arith(arith, label, argc, argv);
1440 }
1441 
compile_cmp_weq(char * label,long wid,unsigned argc,struct symb_s * argv)1442 void compile_cmp_weq(char*label, long wid,
1443 		     unsigned argc, struct symb_s*argv)
1444 {
1445       assert( wid > 0 );
1446 
1447       if (argc != 2) {
1448 	    fprintf(stderr, "%s .cmp/weq has wrong number of symbols\n",label);
1449 	    compile_errors += 1;
1450 	    return;
1451       }
1452 
1453       vvp_arith_ *arith = new vvp_cmp_weq(wid);
1454 
1455       make_arith(arith, label, argc, argv);
1456 }
1457 
compile_cmp_wne(char * label,long wid,unsigned argc,struct symb_s * argv)1458 void compile_cmp_wne(char*label, long wid,
1459 		     unsigned argc, struct symb_s*argv)
1460 {
1461       assert( wid > 0 );
1462 
1463       if (argc != 2) {
1464 	    fprintf(stderr, "%s .cmp/wne has wrong number of symbols\n",label);
1465 	    compile_errors += 1;
1466 	    return;
1467       }
1468 
1469       vvp_arith_ *arith = new vvp_cmp_wne(wid);
1470 
1471       make_arith(arith, label, argc, argv);
1472 }
1473 
1474 
compile_delay(char * label,unsigned width,vvp_delay_t * delay,struct symb_s arg)1475 void compile_delay(char*label, unsigned width,
1476                    vvp_delay_t*delay, struct symb_s arg)
1477 {
1478       vvp_net_t*net = new vvp_net_t;
1479       vvp_fun_delay*obj = new vvp_fun_delay(net, width, *delay);
1480       net->fun = obj;
1481 
1482       delete delay;
1483 
1484       input_connect(net, 0, arg.text);
1485 
1486       define_functor_symbol(label, net);
1487       free(label);
1488 }
1489 
compile_delay(char * label,unsigned width,unsigned argc,struct symb_s * argv,bool ignore_decay)1490 void compile_delay(char*label, unsigned width,
1491                    unsigned argc, struct symb_s*argv, bool ignore_decay)
1492 {
1493       vvp_delay_t stub (0, 0, 0);
1494       if (ignore_decay) stub.set_ignore_decay();
1495       vvp_net_t*net = new vvp_net_t;
1496       vvp_fun_delay*obj = new vvp_fun_delay(net, width, stub);
1497       net->fun = obj;
1498 
1499       inputs_connect(net, argc, argv);
1500       free(argv);
1501 
1502       define_functor_symbol(label, net);
1503       free(label);
1504 }
1505 
1506 /*
1507  * Extend nodes.
1508  */
compile_extend_signed(char * label,long wid,struct symb_s arg)1509 void compile_extend_signed(char*label, long wid, struct symb_s arg)
1510 {
1511       assert(wid >= 0);
1512 
1513       vvp_fun_extend_signed*fun = new vvp_fun_extend_signed(wid);
1514       vvp_net_t*ptr = new vvp_net_t;
1515       ptr->fun = fun;
1516 
1517       define_functor_symbol(label, ptr);
1518       free(label);
1519 
1520       input_connect(ptr, 0, arg.text);
1521 }
1522 
compile_modpath(char * label,unsigned width,struct symb_s drv,struct symb_s dest)1523 struct __vpiModPath* compile_modpath(char*label, unsigned width,
1524                                      struct symb_s drv, struct symb_s dest)
1525 {
1526       vvp_net_t*net = new vvp_net_t;
1527       vvp_fun_modpath*obj = new vvp_fun_modpath(net, width);
1528       net->fun = obj;
1529 
1530       input_connect(net, 0, drv.text);
1531 
1532       define_functor_symbol(label, net);
1533 
1534       __vpiModPath*modpath = vpip_make_modpath(net);
1535 
1536       compile_vpi_lookup(&modpath->path_term_out.expr, dest.text);
1537 
1538       free(label);
1539 
1540       modpath->modpath = obj;
1541       return modpath;
1542 }
1543 
make_modpath_src(struct __vpiModPath * path,char edge,const struct symb_s & src,struct numbv_s & vals,bool ifnone)1544 static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path,
1545 					       char edge,
1546 					       const struct symb_s&src,
1547 					       struct numbv_s&vals,
1548 					       bool ifnone)
1549 {
1550       vvp_fun_modpath*dst = path->modpath;
1551 
1552       vvp_time64_t use_delay[12];
1553       assert(vals.cnt == 12);
1554       for (unsigned idx = 0 ; idx < vals.cnt ;  idx += 1) {
1555 	    use_delay[idx] = vals.nvec[idx];
1556       }
1557 
1558       numbv_clear(&vals);
1559 
1560       vvp_fun_modpath_src*obj = 0;
1561 
1562       int vpi_edge = vpiNoEdge;
1563       if (edge == 0) {
1564 	    obj = new vvp_fun_modpath_src(use_delay);
1565 
1566       } else {
1567 	    bool posedge, negedge;
1568 	    switch (edge) {
1569 		case '+':
1570 		  vpi_edge = vpiPosedge;
1571 		  posedge = true;
1572 		  negedge = false;
1573 		  break;
1574 		case '-':
1575 		  vpi_edge = vpiNegedge;
1576 		  posedge = false;
1577 		  negedge = true;
1578 		  break;
1579 #if 0
1580 		case '*':
1581 		  posedge = true;
1582 		  negedge = true;
1583 		  break;
1584 #endif
1585 		default:
1586 		  posedge = false;
1587 		  negedge = false;
1588 		  fprintf(stderr, "Unknown edge identifier %c(%d).\n", edge,
1589 		          edge);
1590 		  assert(0);
1591 	    }
1592 	    obj = new vvp_fun_modpath_edge(use_delay, posedge, negedge);
1593       }
1594 
1595       vvp_net_t*net = new vvp_net_t;
1596       struct __vpiModPathSrc* srcobj = vpip_make_modpath_src(path, net) ;
1597       vpip_attach_to_current_scope(srcobj);
1598       net->fun = obj;
1599 
1600 	/* Save the vpiEdge directory into the input path term. */
1601       srcobj->path_term_in.edge = vpi_edge;
1602       input_connect(net, 0, src.text);
1603       dst->add_modpath_src(obj, ifnone);
1604 
1605       return srcobj;
1606 }
1607 
compile_modpath_src(struct __vpiModPath * dst,char edge,const struct symb_s & src,struct numbv_s & vals,const struct symb_s & condit_src,const struct symb_s & path_term_in)1608 void compile_modpath_src(struct __vpiModPath*dst, char edge,
1609 			 const struct symb_s&src,
1610 			 struct numbv_s&vals,
1611 			 const struct symb_s&condit_src,
1612 			 const struct symb_s&path_term_in)
1613 {
1614       struct __vpiModPathSrc*obj =
1615 	    make_modpath_src(dst, edge, src, vals, false);
1616       input_connect(obj->net, 1, condit_src.text);
1617       compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text);
1618 }
1619 
compile_modpath_src(struct __vpiModPath * dst,char edge,const struct symb_s & src,struct numbv_s & vals,int condit_src,const struct symb_s & path_term_in,bool ifnone)1620 void compile_modpath_src(struct __vpiModPath*dst, char edge,
1621 			 const struct symb_s&src,
1622 			 struct numbv_s&vals,
1623 			 int condit_src,
1624 			 const struct symb_s&path_term_in,
1625 			 bool ifnone)
1626 {
1627       assert(condit_src == 0);
1628       struct __vpiModPathSrc*obj =
1629 	    make_modpath_src(dst, edge, src, vals, ifnone);
1630       compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text);
1631 }
1632 
1633 /*
1634  * A .shift/l statement creates an array of functors for the
1635  * width. The 0 input is the data vector to be shifted and the 1 input
1636  * is the amount of the shift. An unconnected shift amount is set to 0.
1637  */
compile_shiftl(char * label,long wid,unsigned argc,struct symb_s * argv)1638 void compile_shiftl(char*label, long wid, unsigned argc, struct symb_s*argv)
1639 {
1640       assert( wid > 0 );
1641 
1642       vvp_arith_ *arith = new vvp_shiftl(wid);
1643       make_arith(arith, label, argc, argv);
1644 }
1645 
compile_shiftr(char * label,long wid,bool signed_flag,unsigned argc,struct symb_s * argv)1646 void compile_shiftr(char*label, long wid, bool signed_flag,
1647 		    unsigned argc, struct symb_s*argv)
1648 {
1649       assert( wid > 0 );
1650 
1651       vvp_arith_ *arith = new vvp_shiftr(wid, signed_flag);
1652       make_arith(arith, label, argc, argv);
1653 }
1654 
compile_resolver(char * label,char * type,unsigned argc,struct symb_s * argv)1655 void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
1656 {
1657       vvp_net_t*net = new vvp_net_t;
1658 
1659       resolv_core*core = 0;
1660 
1661       if (strcmp(type,"tri") == 0) {
1662 	    core = new resolv_tri(argc, net, vvp_scalar_t(BIT4_Z, 0,0));
1663 
1664       } else if (strcmp(type,"tri0") == 0) {
1665 	    core = new resolv_tri(argc, net, vvp_scalar_t(BIT4_0, 5,5));
1666 
1667       } else if (strcmp(type,"tri1") == 0) {
1668 	    core = new resolv_tri(argc, net, vvp_scalar_t(BIT4_1, 5,5));
1669 
1670       } else if (strcmp(type,"triand") == 0) {
1671 	    core = new resolv_triand(argc, net);
1672 
1673       } else if (strcmp(type,"trior") == 0) {
1674 	    core = new resolv_trior(argc, net);
1675 
1676       } else {
1677 	    fprintf(stderr, "invalid resolver type: %s\n", type);
1678 	    compile_errors += 1;
1679             delete net;
1680       }
1681 
1682       if (core) {
1683 	    net->fun = core;
1684 	    define_functor_symbol(label, net);
1685 
1686             for (unsigned base = 0 ;  base < argc ;  base += 4) {
1687 	          unsigned nports = argc - base;
1688                   if (nports > 4)
1689                         nports = 4;
1690 
1691                   if (base > 0) {
1692                         net = new vvp_net_t;
1693                         net->fun = new resolv_extend(core, base);
1694                   }
1695                   inputs_connect(net, nports, argv+base);
1696             }
1697       }
1698       free(type);
1699       free(label);
1700       free(argv);
1701 }
1702 
compile_udp_def(int sequ,char * label,char * name,unsigned nin,unsigned init,char ** table)1703 void compile_udp_def(int sequ, char *label, char *name,
1704 		     unsigned nin, unsigned init, char **table)
1705 {
1706       if (sequ) {
1707 	    vvp_bit4_t init4;
1708 	    if (init == 0)
1709 		  init4 = BIT4_0;
1710 	    else if (init == 1)
1711 		  init4 = BIT4_1;
1712 	    else
1713 		  init4 = BIT4_X;
1714 
1715 	    vvp_udp_seq_s *u = new vvp_udp_seq_s(label, name, nin, init4);
1716 	    u->compile_table(table);
1717       } else {
1718 	    vvp_udp_comb_s *u = new vvp_udp_comb_s(label, name, nin);
1719 	    u->compile_table(table);
1720       }
1721       free(label);
1722 }
1723 
compile_udp_table(char ** table,char * row)1724 char **compile_udp_table(char **table, char *row)
1725 {
1726   if (table)
1727     assert(strlen(*table)==strlen(row));
1728 
1729   char **tt;
1730   for (tt = table; tt && *tt; tt++) { }
1731   int n = (tt-table) + 2;
1732 
1733   table = (char**)realloc(table, n*sizeof(char*));
1734   table[n-2] = row;
1735   table[n-1] = 0x0;
1736 
1737   return table;
1738 }
1739 
1740 
1741 /*
1742  * The parser uses this function to compile and link an executable
1743  * opcode. I do this by looking up the opcode in the opcode_table. The
1744  * table gives the operand structure that is acceptable, so I can
1745  * process the operands here as well.
1746  */
compile_code(char * label,char * mnem,comp_operands_t opa)1747 void compile_code(char*label, char*mnem, comp_operands_t opa)
1748 {
1749 	/* First, I can give the label a value that is the current
1750 	   codespace pointer. Don't need the text of the label after
1751 	   this is done. */
1752       if (label)
1753 	    compile_codelabel(label);
1754 
1755 	/* Lookup the opcode in the opcode table. */
1756       struct opcode_table_s*op = (struct opcode_table_s*)
1757 	    bsearch(mnem, opcode_table, opcode_count,
1758 		    sizeof(struct opcode_table_s), &opcode_compare);
1759       if (op == 0) {
1760 	    yyerror("Invalid opcode");
1761 	    compile_errors += 1;
1762 	    return;
1763       }
1764 
1765       assert(op);
1766 
1767 	/* Build up the code from the information about the opcode and
1768 	   the information from the compiler. */
1769       vvp_code_t code = codespace_allocate();
1770       code->opcode = op->opcode;
1771 
1772       if (op->argc != (opa? opa->argc : 0)) {
1773 	    yyerror("operand count");
1774 	    compile_errors += 1;
1775 	    return;
1776       }
1777 
1778 	/* Pull the operands that the instruction expects from the
1779 	   list that the parser supplied. */
1780 
1781       for (unsigned idx = 0 ;  idx < op->argc ;  idx += 1) {
1782 
1783 	    switch (op->argt[idx]) {
1784 		case OA_NONE:
1785 		  break;
1786 
1787 		case OA_ARR_PTR:
1788 		  if (opa->argv[idx].ltype != L_SYMB) {
1789 			yyerror("operand format");
1790 			break;
1791 		  }
1792 
1793 		  compile_array_lookup(code, opa->argv[idx].symb.text);
1794 		  break;
1795 
1796 		case OA_BIT1:
1797 		  if (opa->argv[idx].ltype != L_NUMB) {
1798 			yyerror("operand format");
1799 			break;
1800 		  }
1801 		  code->bit_idx[0] = opa->argv[idx].numb;
1802 		  break;
1803 
1804 		case OA_BIT2:
1805 		  if (opa->argv[idx].ltype != L_NUMB) {
1806 			yyerror("operand format");
1807 			break;
1808 		  }
1809 		  code->bit_idx[1] = opa->argv[idx].numb;
1810 		  break;
1811 
1812 		case OA_CODE_PTR:
1813 		case OA_CODE_PTR2:
1814 		  if (opa->argv[idx].ltype != L_SYMB) {
1815 			yyerror("operand format");
1816 			break;
1817 		  }
1818 
1819 		  assert(opa->argv[idx].symb.idx == 0);
1820 		  code_label_lookup(code, opa->argv[idx].symb.text,
1821 				    op->argt[idx]==OA_CODE_PTR2);
1822 		  break;
1823 
1824 		case OA_FUNC_PTR:
1825 		    /* The operand is a functor. Resolve the label to
1826 		       a functor pointer, or postpone the resolution
1827 		       if it is not defined yet. */
1828 		  if (opa->argv[idx].ltype != L_SYMB) {
1829 			yyerror("operand format");
1830 			break;
1831 		  }
1832 
1833 		  functor_ref_lookup(&code->net, opa->argv[idx].symb.text);
1834 		  break;
1835 
1836 		case OA_FUNC_PTR2:
1837 		    /* The operand is a functor. Resolve the label to
1838 		       a functor pointer, or postpone the resolution
1839 		       if it is not defined yet. */
1840 		  if (opa->argv[idx].ltype != L_SYMB) {
1841 			yyerror("operand format");
1842 			break;
1843 		  }
1844 
1845 		  functor_ref_lookup(&code->net2, opa->argv[idx].symb.text);
1846 		  break;
1847 
1848 		case OA_NUMBER:
1849 		  if (opa->argv[idx].ltype != L_NUMB) {
1850 			yyerror("operand format");
1851 			break;
1852 		  }
1853 
1854 		  code->number = opa->argv[idx].numb;
1855 		  break;
1856 
1857 		case OA_VPI_PTR:
1858 		    /* The operand is a functor. Resolve the label to
1859 		       a functor pointer, or postpone the resolution
1860 		       if it is not defined yet. */
1861 		  if (opa->argv[idx].ltype != L_SYMB) {
1862 			yyerror("operand format");
1863 			break;
1864 		  }
1865 
1866 		  compile_vpi_lookup(&code->handle, opa->argv[idx].symb.text);
1867 		  break;
1868 
1869 		case OA_STRING:
1870 		  if (opa->argv[idx].ltype != L_STRING) {
1871 			yyerror("operand format");
1872 			break;
1873 		  }
1874 
1875 		  code->text = opa->argv[idx].text;
1876 		  break;
1877 	    }
1878       }
1879 
1880       free(opa);
1881 
1882       free(mnem);
1883 }
1884 
compile_codelabel(char * label)1885 void compile_codelabel(char*label)
1886 {
1887       symbol_value_t val;
1888       vvp_code_t ptr = codespace_next();
1889 
1890       val.ptr = ptr;
1891       sym_set_value(sym_codespace, label, val);
1892 
1893       free(label);
1894 }
1895 
compile_file_line(char * label,long file_idx,long lineno,char * description)1896 void compile_file_line(char*label, long file_idx, long lineno,
1897                        char*description)
1898 {
1899       if (label) compile_codelabel(label);
1900 
1901 	/* Create an instruction in the code space. */
1902       vvp_code_t code = codespace_allocate();
1903       code->opcode = &of_FILE_LINE;
1904 
1905 	/* Create a vpiHandle that contains the information. */
1906       code->handle = vpip_build_file_line(description, file_idx, lineno);
1907       assert(code->handle);
1908 
1909 	/* Done with the lexor-allocated name string. */
1910       delete[] description;
1911 }
1912 
compile_vpi_call(char * label,char * name,bool func_as_task_err,bool func_as_task_warn,long file_idx,long lineno,unsigned argc,vpiHandle * argv,unsigned vec4_stack,unsigned real_stack,unsigned string_stack)1913 void compile_vpi_call(char*label, char*name,
1914                       bool func_as_task_err, bool func_as_task_warn,
1915                       long file_idx, long lineno,
1916                       unsigned argc, vpiHandle*argv,
1917 		      unsigned vec4_stack, unsigned real_stack, unsigned string_stack)
1918 {
1919       if (label)
1920 	    compile_codelabel(label);
1921 
1922 	/* Create an instruction in the code space. */
1923       vvp_code_t code = codespace_allocate();
1924       code->opcode = &of_VPI_CALL;
1925 
1926 	/* Create a vpiHandle that bundles the call information, and
1927 	   store that handle in the instruction. */
1928       code->handle = vpip_build_vpi_call(name, 0, 0,
1929 					 0, func_as_task_err, func_as_task_warn,
1930                                          argc, argv, vec4_stack, real_stack, string_stack,
1931 					 file_idx, lineno);
1932       if (code->handle == 0)
1933 	    compile_errors += 1;
1934 
1935 	/* Done with the lexor-allocated name string. */
1936       delete[] name;
1937 }
1938 
compile_vpi_func_call(char * label,char * name,int val_type,unsigned val_wid,long file_idx,long lineno,unsigned argc,vpiHandle * argv,unsigned vec4_stack,unsigned real_stack,unsigned string_stack)1939 void compile_vpi_func_call(char*label, char*name,
1940 			   int val_type, unsigned val_wid,
1941 			   long file_idx, long lineno,
1942 			   unsigned argc, vpiHandle*argv,
1943 			   unsigned vec4_stack,
1944 			   unsigned real_stack,
1945 			   unsigned string_stack)
1946 {
1947       if (label)
1948 	    compile_codelabel(label);
1949 
1950 	/* Create an instruction in the code space. */
1951       vvp_code_t code = codespace_allocate();
1952       code->opcode = &of_VPI_CALL;
1953 
1954 	/* Create a vpiHandle that bundles the call information, and
1955 	   store that handle in the instruction. */
1956       code->handle = vpip_build_vpi_call(name, val_type, val_wid,
1957 					 0, true, false,
1958                                          argc, argv, vec4_stack, real_stack, string_stack,
1959 					 file_idx, lineno);
1960       if (code->handle == 0)
1961 	    compile_errors += 1;
1962 
1963 	/* Done with the lexor-allocated name string. */
1964       delete[] name;
1965 }
1966 
1967 /*
1968  * When the parser finds a thread statement, I create a new thread
1969  * with the start address referenced by the program symbol passed to
1970  * me.
1971  */
compile_thread(char * start_sym,char * flag)1972 void compile_thread(char*start_sym, char*flag)
1973 {
1974       bool push_flag = false;
1975 
1976       symbol_value_t tmp = sym_get_value(sym_codespace, start_sym);
1977       vvp_code_t pc = reinterpret_cast<vvp_code_t>(tmp.ptr);
1978       if (pc == 0) {
1979 	    yyerror("unresolved address");
1980 	    return;
1981       }
1982 
1983       if (flag && (strcmp(flag,"$push") == 0))
1984 	    push_flag = true;
1985 
1986       vthread_t thr = vthread_new(pc, vpip_peek_current_scope());
1987 
1988       if (flag && (strcmp(flag,"$init") == 0))
1989 	    schedule_init_vthread(thr);
1990       else if (flag && (strcmp(flag,"$final") == 0))
1991 	    schedule_final_vthread(thr);
1992       else
1993 	    schedule_vthread(thr, 0, push_flag);
1994 
1995       free(start_sym);
1996       free(flag);
1997 }
1998 
compile_param_logic(char * label,char * name,char * value,bool signed_flag,bool local_flag,long file_idx,long lineno)1999 void compile_param_logic(char*label, char*name, char*value, bool signed_flag,
2000                          bool local_flag,
2001                          long file_idx, long lineno)
2002 {
2003       vvp_vector4_t value4 = c4string_to_vector4(value);
2004       vpiHandle obj = vpip_make_binary_param(name, value4, signed_flag,
2005                                               local_flag, file_idx, lineno);
2006       compile_vpi_symbol(label, obj);
2007       vpip_attach_to_current_scope(obj);
2008 
2009       free(label);
2010       free(value);
2011 }
2012 
compile_param_string(char * label,char * name,char * value,bool local_flag,long file_idx,long lineno)2013 void compile_param_string(char*label, char*name, char*value,
2014                           bool local_flag,
2015                           long file_idx, long lineno)
2016 {
2017 	// name and value become owned by vpip_make_string_param
2018       vpiHandle obj = vpip_make_string_param(name, value, local_flag, file_idx, lineno);
2019       compile_vpi_symbol(label, obj);
2020       vpip_attach_to_current_scope(obj);
2021 
2022       free(label);
2023 }
2024 
compile_param_real(char * label,char * name,char * value,bool local_flag,long file_idx,long lineno)2025 void compile_param_real(char*label, char*name, char*value,
2026                         bool local_flag,
2027                         long file_idx, long lineno)
2028 {
2029       double dvalue = crstring_to_double(value);
2030       vpiHandle obj = vpip_make_real_param(name, dvalue, local_flag, file_idx, lineno);
2031       compile_vpi_symbol(label, obj);
2032       vpip_attach_to_current_scope(obj);
2033 
2034       free(label);
2035       free(value);
2036 }
2037 
compile_island(char * label,char * type)2038 void compile_island(char*label, char*type)
2039 {
2040       if (strcmp(type,"tran") == 0)
2041 	    compile_island_tran(label);
2042       else
2043 	    assert(0);
2044 
2045       free(type);
2046 }
2047