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