Add file and line information for parameters, etc.
[sverilog.git] / vvp / compile.cc
blobe152ff7e03a8b0e8de492ddea90380b70985a063
1 /*
2 * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 # include "arith.h"
21 # include "compile.h"
22 # include "logic.h"
23 # include "resolv.h"
24 # include "udp.h"
25 # include "memory.h"
26 # include "symbols.h"
27 # include "codes.h"
28 # include "schedule.h"
29 # include "vpi_priv.h"
30 # include "parse_misc.h"
31 # include "statistics.h"
32 #ifdef HAVE_MALLOC_H
33 # include <malloc.h>
34 #endif
35 # include <iostream>
36 # include <list>
37 # include <stdlib.h>
38 # include <string.h>
39 # include <assert.h>
41 #ifdef __MINGW32__
42 #include <windows.h>
43 #endif
45 unsigned compile_errors = 0;
48 * The opcode table lists all the code mnemonics, along with their
49 * opcode and operand types. The table is written sorted by mnemonic
50 * so that it can be searched by binary search. The opcode_compare
51 * function is a helper function for that lookup.
54 enum operand_e {
55 /* Place holder for unused operand */
56 OA_NONE,
57 /* The operand is a number, an immediate unsigned integer */
58 OA_NUMBER,
59 /* The operand is a pointer to an array. */
60 OA_ARR_PTR,
61 /* The operand is a thread bit index or short integer */
62 OA_BIT1,
63 OA_BIT2,
64 /* The operand is a pointer to code space */
65 OA_CODE_PTR,
66 /* The operand is a variable or net pointer */
67 OA_FUNC_PTR,
68 /* The operand is a second functor pointer */
69 OA_FUNC_PTR2,
70 /* The operand is a pointer to a memory */
71 OA_MEM_PTR,
72 /* The operand is a VPI handle */
73 OA_VPI_PTR,
76 struct opcode_table_s {
77 const char*mnemonic;
78 vvp_code_fun opcode;
80 unsigned argc;
81 enum operand_e argt[OPERAND_MAX];
84 const static struct opcode_table_s opcode_table[] = {
85 { "%add", of_ADD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
86 { "%add/wr", of_ADD_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
87 { "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
88 { "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
89 { "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
90 { "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
91 { "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
92 { "%assign/mv",of_ASSIGN_MV,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
93 { "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
94 { "%assign/v0/d",of_ASSIGN_V0D,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
95 { "%assign/v0/x1",of_ASSIGN_V0X1,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
96 { "%assign/v0/x1/d",of_ASSIGN_V0X1D,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
97 { "%assign/wr",of_ASSIGN_WR,3,{OA_VPI_PTR,OA_BIT1, OA_BIT2} },
98 { "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
99 { "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
100 { "%blend/wr", of_BLEND_WR,2, {OA_BIT1, OA_BIT2, OA_NONE} },
101 { "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
102 { "%cassign/link",of_CASSIGN_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
103 { "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
104 { "%cassign/wr",of_CASSIGN_WR,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
105 { "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
106 { "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
107 { "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
108 { "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
109 { "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
110 { "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
111 { "%cmp/x", of_CMPX, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
112 { "%cmp/z", of_CMPZ, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
113 { "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
114 { "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
115 { "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
116 { "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
117 { "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
118 { "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
119 { "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
120 { "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
121 { "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
122 { "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
123 { "%div/s", of_DIV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
124 { "%div/wr", of_DIV_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
125 { "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
126 { "%force/link",of_FORCE_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
127 { "%force/v",of_FORCE_V,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
128 { "%force/wr",of_FORCE_WR,2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
129 { "%force/x0",of_FORCE_X0,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
130 { "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
131 { "%ix/add", of_IX_ADD, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
132 { "%ix/get", of_IX_GET, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
133 { "%ix/get/s",of_IX_GET_S,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
134 { "%ix/getv",of_IX_GETV,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
135 { "%ix/load",of_IX_LOAD,2, {OA_BIT1, OA_NUMBER, OA_NONE} },
136 { "%ix/mul", of_IX_MUL, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
137 { "%ix/sub", of_IX_SUB, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
138 { "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
139 { "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
140 { "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
141 { "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
142 { "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
143 { "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
144 { "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
145 { "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
146 { "%load/mv",of_LOAD_MV,3, {OA_BIT1, OA_MEM_PTR, OA_BIT2} },
147 { "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
148 { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
149 { "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
150 { "%load/wr",of_LOAD_WR,2, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
151 { "%load/x", of_LOAD_X, 3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
152 { "%load/x.p",of_LOAD_XP, 3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
153 { "%loadi/wr",of_LOADI_WR,3,{OA_BIT1, OA_NUMBER, OA_BIT2} },
154 { "%mod", of_MOD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
155 { "%mod/s", of_MOD_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
156 { "%mod/wr", of_MOD_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
157 { "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
158 { "%mov/wr", of_MOV_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
159 { "%movi", of_MOVI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
160 { "%mul", of_MUL, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
161 { "%mul/wr", of_MUL_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
162 { "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
163 { "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
164 { "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
165 { "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} },
166 { "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
167 { "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
168 { "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
169 { "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
170 { "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
171 { "%pow/wr", of_POW_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
172 { "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
173 { "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
174 { "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
175 { "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
176 { "%set/mv", of_SET_MV, 3, {OA_MEM_PTR, OA_BIT1, OA_BIT2} },
177 { "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
178 { "%set/wr", of_SET_WORDR,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
179 { "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
180 // { "%set/x0/x",of_SET_X0_X,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
181 { "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
182 { "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
183 { "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
184 { "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
185 { "%sub/wr", of_SUB_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
186 { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
187 { "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
188 { "%xnor", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
189 { "%xnor/r", of_XNORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
190 { "%xor", of_XOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
191 { "%xor/r", of_XORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
192 { 0, of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }
195 static const unsigned opcode_count =
196 sizeof(opcode_table)/sizeof(*opcode_table) - 1;
198 static int opcode_compare(const void*k, const void*r)
200 const char*kp = (const char*)k;
201 const struct opcode_table_s*rp = (const struct opcode_table_s*)r;
202 return strcmp(kp, rp->mnemonic);
206 * Keep a symbol table of addresses within code space. Labels on
207 * executable opcodes are mapped to their address here.
209 static symbol_table_t sym_codespace = 0;
212 * Keep a symbol table of functors mentioned in the source. This table
213 * is used to resolve references as they come.
215 static symbol_table_t sym_functors = 0;
218 * VPI objects are indexed during compile time so that they can be
219 * linked together as they are created. This symbol table matches
220 * labels to vpiHandles.
222 static symbol_table_t sym_vpi = 0;
226 * If a functor parameter makes a forward reference to a functor, then
227 * I need to save that reference and resolve it after the functors are
228 * created. Use this structure to keep the unresolved references in an
229 * unsorted singly linked list.
231 * The postpone_functor_input arranges for a functor input to be
232 * resolved and connected at cleanup. This is used if the symbol is
233 * defined after its use in a functor. The ptr parameter is the
234 * complete vvp_input_t for the input port.
239 * Add a functor to the symbol table
242 void define_functor_symbol(const char*label, vvp_net_t*net)
244 symbol_value_t val;
245 val.net = net;
246 sym_set_value(sym_functors, label, val);
249 static vvp_net_t*lookup_functor_symbol(const char*label)
251 assert(sym_functors);
252 symbol_value_t val = sym_get_value(sym_functors, label);
253 return val.net;
256 vpiHandle vvp_lookup_handle(const char*label)
258 symbol_value_t val = sym_get_value(sym_vpi, label);
259 if (val.ptr) return (vpiHandle) val.ptr;
260 return 0;
263 vvp_net_t* vvp_net_lookup(const char*label)
265 /* First, look to see if the symbol is a vpi object of some
266 sort. If it is, then get the vvp_ipoint_t pointer out of
267 the vpiHandle. */
268 symbol_value_t val = sym_get_value(sym_vpi, label);
269 if (val.ptr) {
270 vpiHandle vpi = (vpiHandle) val.ptr;
271 switch (vpi->vpi_type->type_code) {
272 case vpiNet:
273 case vpiReg:
274 case vpiIntegerVar: {
275 __vpiSignal*sig = (__vpiSignal*)vpi;
276 return sig->node;
279 case vpiRealVar: {
280 __vpiRealVar*sig = (__vpiRealVar*)vpi;
281 return sig->net;
284 case vpiNamedEvent: {
285 __vpiNamedEvent*tmp = (__vpiNamedEvent*)vpi;
286 return tmp->funct;
289 default:
290 fprintf(stderr, "Unsupported type %d.\n",
291 vpi->vpi_type->type_code);
292 assert(0);
297 /* Failing that, look for a general functor. */
298 vvp_net_t*tmp = lookup_functor_symbol(label);
300 return tmp;
304 * The resolv_list_s is the base class for a symbol resolve action, and
305 * the resolv_list is an unordered list of these resolve actions. Some
306 * function creates an instance of a resolv_list_s object that
307 * contains the data pertinent to that resolution request, and
308 * executes it with the resolv_submit function. If the operation can
309 * complete, then the resolv_submit deletes the object. Otherwise, it
310 * pushes it onto the resolv_list for later processing.
312 * Derived classes implement the resolve function to perform the
313 * actual binding or resolution that the instance requires. If the
314 * function succeeds, the resolve method returns true and the object
315 * can be deleted any time.
317 * The mes parameter of the resolve method tells the resolver that
318 * this call is its last chance. If it cannot complete the operation,
319 * it must print an error message and return false.
321 static struct resolv_list_s*resolv_list = 0;
323 struct resolv_list_s {
324 virtual ~resolv_list_s() { }
325 struct resolv_list_s*next;
326 virtual bool resolve(bool mes = false) = 0;
329 static void resolv_submit(struct resolv_list_s*cur)
331 if (cur->resolve()) {
332 delete cur;
333 return;
336 cur->next = resolv_list;
337 resolv_list = cur;
342 * Look up vvp_nets in the symbol table. The "source" is the label for
343 * the net that I want to feed, and net->port[port] is the vvp_net
344 * input that I want that node to feed into. When the name is found,
345 * put net->port[port] into the fan-out list for that node.
347 struct vvp_net_resolv_list_s: public resolv_list_s {
348 // node to locate
349 char*source;
350 // port to be driven by the located node.
351 vvp_net_ptr_t port;
352 virtual bool resolve(bool mes);
355 bool vvp_net_resolv_list_s::resolve(bool mes)
357 vvp_net_t*tmp = vvp_net_lookup(source);
359 if (tmp) {
360 // Link the input port to the located output.
361 vvp_net_t*net = port.ptr();
362 net->port[port.port()] = tmp->out;
363 tmp->out = port;
365 free(source);
366 return true;
369 if (mes)
370 fprintf(stderr, "unresolved vvp_net reference: %s\n", source);
372 return false;
375 inline static
376 void postpone_functor_input(vvp_net_ptr_t port, char*lab)
378 struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s;
380 res->port = port;
381 res->source = lab;
383 resolv_submit(res);
388 * Generic functor reference lookup.
391 struct functor_gen_resolv_list_s: public resolv_list_s {
392 char*source;
393 vvp_net_t**ref;
394 virtual bool resolve(bool mes);
397 bool functor_gen_resolv_list_s::resolve(bool mes)
399 vvp_net_t*tmp = vvp_net_lookup(source);
401 if (tmp) {
402 *ref = tmp;
404 free(source);
405 return true;
408 if (mes)
409 fprintf(stderr, "unresolved functor reference: %s\n", source);
411 return false;
414 void functor_ref_lookup(vvp_net_t**ref, char*lab)
416 struct functor_gen_resolv_list_s*res =
417 new struct functor_gen_resolv_list_s;
419 res->ref = ref;
420 res->source = lab;
422 resolv_submit(res);
426 * vpiHandle lookup
429 struct vpi_handle_resolv_list_s: public resolv_list_s {
430 vpiHandle *handle;
431 char *label;
432 virtual bool resolve(bool mes);
435 bool vpi_handle_resolv_list_s::resolve(bool mes)
437 symbol_value_t val = sym_get_value(sym_vpi, label);
438 if (!val.ptr) {
439 // check for thread vector T<base,wid>
440 unsigned base, wid;
441 unsigned n = 0;
442 char ss[32];
443 if (2 <= sscanf(label, "T<%u,%u>%n", &base, &wid, &n)
444 && n == strlen(label)) {
445 val.ptr = vpip_make_vthr_vector(base, wid, false);
446 sym_set_value(sym_vpi, label, val);
448 } else if (3 <= sscanf(label, "T<%u,%u,%[su]>%n", &base,
449 &wid, ss, &n)
450 && n == strlen(label)) {
452 bool signed_flag = false;
453 for (char*fp = ss ; *fp ; fp += 1) switch (*fp) {
454 case 's':
455 signed_flag = true;
456 break;
457 case 'u':
458 signed_flag = false;
459 break;
460 default:
461 break;
464 val.ptr = vpip_make_vthr_vector(base, wid, signed_flag);
465 sym_set_value(sym_vpi, label, val);
467 } else if (2 == sscanf(label, "W<%u,%[r]>%n", &base, ss, &n)
468 && n == strlen(label)) {
470 val.ptr = vpip_make_vthr_word(base, ss);
471 sym_set_value(sym_vpi, label, val);
476 if (!val.ptr) {
477 // check for memory word M<mem,base,wid>
480 if (val.ptr) {
481 *handle = (vpiHandle) val.ptr;
482 free(label);
483 return true;
486 if (mes)
487 fprintf(stderr, "unresolved vpi name lookup: %s\n", label);
489 return false;
492 void compile_vpi_lookup(vpiHandle *handle, char*label)
494 if (strcmp(label, "$time") == 0) {
495 *handle = vpip_sim_time(vpip_peek_current_scope());
496 free(label);
497 return;
500 if (strcmp(label, "$stime") == 0) {
501 *handle = vpip_sim_time(vpip_peek_current_scope());
502 free(label);
503 return;
506 if (strcmp(label, "$realtime") == 0) {
507 *handle = vpip_sim_realtime(vpip_peek_current_scope());
508 free(label);
509 return;
512 if (strcmp(label, "$simtime") == 0) {
513 *handle = vpip_sim_time(0);
514 free(label);
515 return;
518 struct vpi_handle_resolv_list_s*res
519 = new struct vpi_handle_resolv_list_s;
521 res->handle = handle;
522 res->label = label;
523 resolv_submit(res);
527 * Code Label lookup
530 struct code_label_resolv_list_s: public resolv_list_s {
531 struct vvp_code_s *code;
532 char *label;
533 virtual bool resolve(bool mes);
536 bool code_label_resolv_list_s::resolve(bool mes)
538 symbol_value_t val = sym_get_value(sym_codespace, label);
539 if (val.num) {
540 if (code->opcode == of_FORK)
541 code->cptr2 = reinterpret_cast<vvp_code_t>(val.ptr);
542 else
543 code->cptr = reinterpret_cast<vvp_code_t>(val.ptr);
544 free(label);
545 return true;
548 if (mes)
549 fprintf(stderr,
550 "unresolved code label: %s\n",
551 label);
553 return false;
556 void code_label_lookup(struct vvp_code_s *code, char *label)
558 struct code_label_resolv_list_s *res
559 = new struct code_label_resolv_list_s;
561 res->code = code;
562 res->label = label;
564 resolv_submit(res);
568 * Lookup memories.
570 struct memory_resolv_list_s: public resolv_list_s {
571 struct vvp_code_s *code;
572 char *label;
573 virtual bool resolve(bool mes);
576 bool memory_resolv_list_s::resolve(bool mes)
578 code->mem = memory_find(label);
579 if (code->mem != 0) {
580 free(label);
581 return true;
584 if (mes)
585 fprintf(stderr, "Memory unresolved: %s\n", label);
587 return false;
590 static void compile_mem_lookup(struct vvp_code_s *code, char *label)
592 struct memory_resolv_list_s *res
593 = new struct memory_resolv_list_s;
595 res->code = code;
596 res->label = label;
598 resolv_submit(res);
601 struct array_resolv_list_s: public resolv_list_s {
602 struct vvp_code_s *code;
603 char *label;
604 virtual bool resolve(bool mes);
607 bool array_resolv_list_s::resolve(bool mes)
609 code->array = array_find(label);
610 if (code->array != 0) {
611 free(label);
612 return true;
615 if (mes)
616 fprintf(stderr, "Array unresolved: %s\n", label);
618 return false;
621 static void compile_array_lookup(struct vvp_code_s*code, char*label)
623 struct array_resolv_list_s *res
624 = new struct array_resolv_list_s;
626 res->code = code;
627 res->label = label;
629 resolv_submit(res);
632 static list<struct __vpiSysTaskCall*> scheduled_compiletf;
634 void compile_compiletf(struct __vpiSysTaskCall*obj)
636 if (obj->defn->info.compiletf == 0)
637 return;
639 scheduled_compiletf.push_back(obj);
643 * When parsing is otherwise complete, this function is called to do
644 * the final stuff. Clean up deferred linking here.
647 void compile_cleanup(void)
649 int lnerrs = -1;
650 int nerrs = 0;
651 int last;
653 if (verbose_flag) {
654 fprintf(stderr, " ... Linking\n");
655 fflush(stderr);
658 do {
659 struct resolv_list_s *res = resolv_list;
660 resolv_list = 0x0;
661 last = nerrs == lnerrs;
662 lnerrs = nerrs;
663 nerrs = 0;
664 while (res) {
665 struct resolv_list_s *cur = res;
666 res = res->next;
667 if (cur->resolve(last))
668 delete cur;
669 else {
670 nerrs++;
671 cur->next = resolv_list;
672 resolv_list = cur;
675 if (nerrs && last)
676 fprintf(stderr,
677 "compile_cleanup: %d unresolved items\n",
678 nerrs);
679 } while (nerrs && !last);
681 compile_errors += nerrs;
683 if (verbose_flag) {
684 fprintf(stderr, " ... Removing symbol tables\n");
685 fflush(stderr);
688 /* After compile is complete, the vpi symbol table is no
689 longer needed. VPI objects are located by following
690 scopes. */
691 delete_symbol_table(sym_vpi);
692 sym_vpi = 0;
694 /* Don't need the code labels. The instructions have numeric
695 pointers in them, the symbol table is no longer needed. */
696 delete_symbol_table(sym_codespace);
697 sym_codespace = 0;
699 delete_symbol_table(sym_functors);
700 sym_functors = 0;
702 if (verbose_flag) {
703 fprintf(stderr, " ... Compiletf functions\n");
704 fflush(stderr);
707 assert(vpi_mode_flag == VPI_MODE_NONE);
708 vpi_mode_flag = VPI_MODE_COMPILETF;
710 while (! scheduled_compiletf.empty()) {
711 struct __vpiSysTaskCall*obj = scheduled_compiletf.front();
712 scheduled_compiletf.pop_front();
713 vpip_cur_task = obj;
714 obj->defn->info.compiletf (obj->defn->info.user_data);
715 vpip_cur_task = 0;
718 vpi_mode_flag = VPI_MODE_NONE;
721 void compile_vpi_symbol(const char*label, vpiHandle obj)
723 symbol_value_t val;
724 val.ptr = obj;
725 sym_set_value(sym_vpi, label, val);
729 * Initialize the compiler by allocation empty symbol tables and
730 * initializing the various address spaces.
732 void compile_init(void)
734 sym_vpi = new_symbol_table();
736 sym_functors = new_symbol_table();
738 sym_codespace = new_symbol_table();
739 codespace_init();
742 void compile_load_vpi_module(char*name)
744 vpip_load_module(name);
745 free(name);
748 void compile_vpi_time_precision(long pre)
750 vpip_set_time_precision(pre);
754 * Convert a Cr string value to double.
756 * The format is broken into mantissa and exponent.
757 * The exponent in turn includes a sign bit.
759 * The mantissa is a 64bit integer value (encoded in hex).
761 * The exponent included the sign bit (0x4000) and the binary
762 * exponent offset by 0x1000. The actual exponent is the
763 * encoded exponent - 0x1000.
765 * The real value is sign * (mant ** exp).
767 double crstring_to_double(char*label)
769 char*cp = label+3;
770 assert(*cp == 'm');
771 cp += 1;
772 uint64_t mant = strtoull(cp, &cp, 16);
773 assert(*cp == 'g');
774 cp += 1;
775 int exp = strtoul(cp, 0, 16);
777 double tmp;
778 if (mant == 0 && exp == 0x3fff) {
779 tmp = INFINITY;
780 } else if (mant == 0 && exp == 0x7fff) {
781 tmp = -INFINITY;
782 } else if (exp == 0x3fff) {
783 tmp = nan("");
784 } else {
785 double sign = (exp & 0x4000)? -1.0 : 1.0;
786 exp &= 0x1fff;
788 tmp = sign * ldexp((double)mant, exp - 0x1000);
791 return tmp;
795 * Run through the arguments looking for the nodes that are
796 * connected to my input ports. For each source functor that I
797 * find, connect the output of that functor to the indexed
798 * input by inserting myself (complete with the port number in
799 * the vvp_ipoint_t) into the list that the source heads.
801 * If the source functor is not declared yet, then don't do
802 * the link yet. Save the reference to be resolved later.
804 * If the source is a constant value, then set the ival of the functor
805 * and skip the symbol lookup.
808 void input_connect(vvp_net_t*fdx, unsigned port, char*label)
810 vvp_net_ptr_t ifdx = vvp_net_ptr_t(fdx, port);
811 char*tp;
813 /* Is this a vvp_vector4_t constant value? */
814 if ((strncmp(label, "C4<", 3) == 0)
815 && ((tp = strchr(label,'>')))
816 && (tp[1] == 0)
817 && (strspn(label+3, "01xz")+3 == (unsigned)(tp-label))) {
819 vvp_vector4_t tmp = c4string_to_vector4(label);
821 // Inputs that are constants are schedule to execute as
822 // soon at the simulation starts. In Verilog, constants
823 // start propagating when the simulation starts, just
824 // like any other signal value. But letting the
825 // scheduler distribute the constant value has the
826 // additional advantage that the constant is not
827 // propagated until the network is fully linked.
828 schedule_set_vector(ifdx, tmp);
830 free(label);
831 return;
834 /* Is this a vvp_vector8_t constant value? */
835 if ((strncmp(label, "C8<", 3) == 0)
836 && ((tp = strchr(label,'>')))
837 && (tp[1] == 0)
838 && (strspn(label+3, "01234567xz")+3 == (unsigned)(tp-label))) {
840 size_t vsize = tp-label-3;
841 assert(vsize%3 == 0);
842 vsize /= 3;
844 vvp_vector8_t tmp (vsize);
846 for (unsigned idx = 0 ; idx < vsize ; idx += 1) {
847 vvp_bit4_t bit = BIT4_Z;
848 unsigned dr0 = label[3+idx*3+0] - '0';
849 unsigned dr1 = label[3+idx*3+1] - '0';
851 switch (label[3+idx*3+2]) {
852 case '0':
853 bit = BIT4_0;
854 break;
855 case '1':
856 bit = BIT4_1;
857 break;
858 case 'x':
859 bit = BIT4_X;
860 break;
861 case 'z':
862 bit = BIT4_Z;
863 break;
866 tmp.set_bit(vsize-idx-1, vvp_scalar_t(bit, dr0, dr1));
869 schedule_set_vector(ifdx, tmp);
871 free(label);
872 return;
875 /* Handle the Cr<> constant driver, which is a real-value
876 driver. */
877 if ((strncmp(label, "Cr<", 3) == 0)
878 && ((tp = strchr(label,'>')))
879 && (tp[1] == 0)
880 && (strspn(label+3, "0123456789abcdefmg")+3 == (unsigned)(tp-label))) {
882 double tmp = crstring_to_double(label);
884 schedule_set_vector(ifdx, tmp);
885 free(label);
886 return;
889 /* Handle the general case that this is a label for a node in
890 the vvp net. This arranges for the label to be preserved in
891 a linker list, and linked when the symbol table is
892 complete. */
893 postpone_functor_input(ifdx, label);
896 void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv)
898 if (argc > 4) {
899 cerr << "XXXX argv[0] = " << argv[0].text << endl;
901 assert(argc <= 4);
903 for (unsigned idx = 0; idx < argc; idx += 1) {
905 input_connect(fdx, idx, argv[idx].text);
909 void wide_inputs_connect(vvp_wide_fun_core*core,
910 unsigned argc, struct symb_s*argv)
912 /* Create input functors to receive values from the
913 network. These functors pass the data to the core. */
914 unsigned input_functors = (argc+3) / 4;
915 for (unsigned idx = 0 ; idx < input_functors ; idx += 1) {
916 unsigned base = idx*4;
917 unsigned trans = 4;
918 if (base+trans > argc)
919 trans = argc - base;
921 vvp_wide_fun_t*cur = new vvp_wide_fun_t(core, base);
922 vvp_net_t*ptr = new vvp_net_t;
923 ptr->fun = cur;
925 inputs_connect(ptr, trans, argv+base);
929 template <class T_> void make_arith(T_ *arith, char*label,
930 unsigned argc, struct symb_s*argv)
932 vvp_net_t* ptr = new vvp_net_t;
933 ptr->fun = arith;
935 define_functor_symbol(label, ptr);
936 free(label);
938 assert(argc == 2);
939 inputs_connect(ptr, argc, argv);
941 free(argv);
944 void compile_arith_div(char*label, long wid, bool signed_flag,
945 unsigned argc, struct symb_s*argv)
947 assert( wid > 0 );
949 if (argc != 2) {
950 const char *suffix = "";
951 if (signed_flag) suffix = ".s";
952 fprintf(stderr, "%s; .arith/div%s has wrong number of "
953 "symbols\n", label, suffix);
954 compile_errors += 1;
955 return;
958 vvp_arith_ *arith = new vvp_arith_div(wid, signed_flag);
959 make_arith(arith, label, argc, argv);
962 void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv)
964 if (argc != 2) {
965 fprintf(stderr, "%s; .arith/divr has wrong number of symbols\n", label);
966 compile_errors += 1;
967 return;
970 vvp_arith_real_ *arith = new vvp_arith_div_real;
971 make_arith(arith, label, argc, argv);
974 void compile_arith_mod(char*label, long wid,
975 unsigned argc, struct symb_s*argv)
977 assert( wid > 0 );
979 if (argc != 2) {
980 fprintf(stderr, "%s .arith/mod has wrong number of symbols\n", label);
981 compile_errors += 1;
982 return;
985 vvp_arith_ *arith = new vvp_arith_mod(wid, false);
987 make_arith(arith, label, argc, argv);
990 void compile_arith_mod_r(char*label, unsigned argc, struct symb_s*argv)
992 if (argc != 2) {
993 fprintf(stderr, "%s .arith/mod.r has wrong number of symbols\n", label);
994 compile_errors += 1;
995 return;
998 vvp_arith_real_ *arith = new vvp_arith_mod_real;
999 make_arith(arith, label, argc, argv);
1002 void compile_arith_mult(char*label, long wid,
1003 unsigned argc, struct symb_s*argv)
1005 assert( wid > 0 );
1007 if (argc != 2) {
1008 fprintf(stderr, "%s .arith/mult has wrong number of symbols\n", label);
1009 compile_errors += 1;
1010 return;
1013 vvp_arith_ *arith = new vvp_arith_mult(wid);
1014 make_arith(arith, label, argc, argv);
1017 void compile_arith_mult_r(char*label, unsigned argc, struct symb_s*argv)
1019 if (argc != 2) {
1020 fprintf(stderr, "%s .arith/mult.r has wrong number of symbols\n", label);
1021 compile_errors += 1;
1022 return;
1025 vvp_arith_real_ *arith = new vvp_arith_mult_real;
1026 make_arith(arith, label, argc, argv);
1030 void compile_arith_pow(char*label, long wid, bool signed_flag,
1031 unsigned argc, struct symb_s*argv)
1033 assert( wid > 0 );
1034 /* For now we need to do a double to long cast, so the number
1035 of bits is limited. This should be caught in the compiler. */
1036 if (signed_flag) {
1037 assert( wid <= (long)(8*sizeof(long)) );
1040 if (argc != 2) {
1041 const char *suffix = "";
1042 if (signed_flag) suffix = ".s";
1043 fprintf(stderr, "%s .arith/pow%s has wrong number of "
1044 "symbols\n", label, suffix);
1045 compile_errors += 1;
1046 return;
1049 vvp_arith_ *arith = new vvp_arith_pow(wid, signed_flag);
1050 make_arith(arith, label, argc, argv);
1053 void compile_arith_pow_r(char*label, unsigned argc, struct symb_s*argv)
1055 if (argc != 2) {
1056 fprintf(stderr, "%s .arith/pow.r has wrong number of symbols\n", label);
1057 compile_errors += 1;
1058 return;
1061 vvp_arith_real_ *arith = new vvp_arith_pow_real;
1062 make_arith(arith, label, argc, argv);
1065 void compile_arith_sub(char*label, long wid, unsigned argc, struct symb_s*argv)
1067 assert( wid > 0 );
1069 if (argc != 2) {
1070 fprintf(stderr, "%s .arith/sub has wrong number of symbols\n", label);
1071 compile_errors += 1;
1072 return;
1075 vvp_arith_ *arith = new vvp_arith_sub(wid);
1076 make_arith(arith, label, argc, argv);
1079 void compile_arith_sub_r(char*label, unsigned argc, struct symb_s*argv)
1081 if (argc != 2) {
1082 fprintf(stderr, "%s; .arith/sub.r has wrong number of symbols\n", label);
1083 compile_errors += 1;
1084 return;
1087 vvp_arith_real_ *arith = new vvp_arith_sub_real;
1088 make_arith(arith, label, argc, argv);
1091 void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
1093 assert( wid > 0 );
1095 if (argc != 2) {
1096 fprintf(stderr, "%s .arith/sum has wrong number of symbols\n", label);
1097 compile_errors += 1;
1098 return;
1101 vvp_arith_ *arith = new vvp_arith_sum(wid);
1102 make_arith(arith, label, argc, argv);
1105 void compile_arith_sum_r(char*label, unsigned argc, struct symb_s*argv)
1107 if (argc != 2) {
1108 fprintf(stderr, "%s .arith/sum.r has wrong number of symbols\n", label);
1109 compile_errors += 1;
1110 return;
1113 vvp_arith_real_ *arith = new vvp_arith_sum_real;
1114 make_arith(arith, label, argc, argv);
1117 void compile_cmp_eeq(char*label, long wid,
1118 unsigned argc, struct symb_s*argv)
1120 assert( wid > 0 );
1122 if (argc != 2) {
1123 fprintf(stderr, "%s .cmp/eeq has wrong number of symbols\n",label);
1124 compile_errors += 1;
1125 return;
1128 vvp_arith_ *arith = new vvp_cmp_eeq(wid);
1130 make_arith(arith, label, argc, argv);
1133 void compile_cmp_nee(char*label, long wid,
1134 unsigned argc, struct symb_s*argv)
1136 assert( wid > 0 );
1138 if (argc != 2) {
1139 fprintf(stderr, "%s .cmp/eeq has wrong number of symbols\n",label);
1140 compile_errors += 1;
1141 return;
1144 vvp_arith_ *arith = new vvp_cmp_nee(wid);
1146 make_arith(arith, label, argc, argv);
1149 void compile_cmp_eq(char*label, long wid, unsigned argc, struct symb_s*argv)
1151 assert( wid > 0 );
1153 if (argc != 2) {
1154 fprintf(stderr, "%s .cmp/eq has wrong number of symbols\n",label);
1155 compile_errors += 1;
1156 return;
1159 vvp_arith_ *arith = new vvp_cmp_eq(wid);
1160 make_arith(arith, label, argc, argv);
1163 void compile_cmp_eq_r(char*label, unsigned argc, struct symb_s*argv)
1165 if (argc != 2) {
1166 fprintf(stderr, "%s .cmp/eq.r has wrong number of symbols\n",label);
1167 compile_errors += 1;
1168 return;
1171 vvp_arith_real_ *arith = new vvp_cmp_eq_real;
1172 make_arith(arith, label, argc, argv);
1175 void compile_cmp_ne(char*label, long wid, unsigned argc, struct symb_s*argv)
1177 assert( wid > 0 );
1179 if (argc != 2) {
1180 fprintf(stderr, "%s .cmp/ne has wrong number of symbols\n",label);
1181 compile_errors += 1;
1182 return;
1185 vvp_arith_ *arith = new vvp_cmp_ne(wid);
1186 make_arith(arith, label, argc, argv);
1189 void compile_cmp_ne_r(char*label, unsigned argc, struct symb_s*argv)
1191 if (argc != 2) {
1192 fprintf(stderr, "%s .cmp/ne.r has wrong number of symbols\n",label);
1193 compile_errors += 1;
1194 return;
1197 vvp_arith_real_ *arith = new vvp_cmp_ne_real;
1198 make_arith(arith, label, argc, argv);
1201 void compile_cmp_ge(char*label, long wid, bool signed_flag,
1202 unsigned argc, struct symb_s*argv)
1204 assert( wid > 0 );
1206 if (argc != 2) {
1207 fprintf(stderr, "%s .cmp/ge has wrong number of symbols\n", label);
1208 compile_errors += 1;
1209 return;
1212 vvp_arith_ *arith = new vvp_cmp_ge(wid, signed_flag);
1214 make_arith(arith, label, argc, argv);
1217 void compile_cmp_ge_r(char*label, unsigned argc, struct symb_s*argv)
1219 if (argc != 2) {
1220 fprintf(stderr, "%s .cmp/ge.r has wrong number of symbols\n",label);
1221 compile_errors += 1;
1222 return;
1225 vvp_arith_real_ *arith = new vvp_cmp_ge_real;
1226 make_arith(arith, label, argc, argv);
1229 void compile_cmp_gt(char*label, long wid, bool signed_flag,
1230 unsigned argc, struct symb_s*argv)
1232 assert( wid > 0 );
1234 if (argc != 2) {
1235 fprintf(stderr, "%s .cmp/gt has wrong number of symbols\n", label);
1236 compile_errors += 1;
1237 return;
1240 vvp_arith_ *arith = new vvp_cmp_gt(wid, signed_flag);
1242 make_arith(arith, label, argc, argv);
1245 void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv)
1247 if (argc != 2) {
1248 fprintf(stderr, "%s .cmp/gt.r has wrong number of symbols\n",label);
1249 compile_errors += 1;
1250 return;
1253 vvp_arith_real_ *arith = new vvp_cmp_gt_real;
1254 make_arith(arith, label, argc, argv);
1258 void compile_delay(char*label, vvp_delay_t*delay, struct symb_s arg)
1260 vvp_net_t*net = new vvp_net_t;
1261 vvp_fun_delay*obj = new vvp_fun_delay(net, BIT4_X, *delay);
1262 net->fun = obj;
1264 delete delay;
1266 input_connect(net, 0, arg.text);
1268 define_functor_symbol(label, net);
1269 free(label);
1272 void compile_delay(char*label, unsigned argc, struct symb_s*argv)
1274 vvp_delay_t stub (0, 0, 0);
1275 vvp_net_t*net = new vvp_net_t;
1276 vvp_fun_delay*obj = new vvp_fun_delay(net, BIT4_X, stub);
1277 net->fun = obj;
1279 inputs_connect(net, argc, argv);
1280 free(argv);
1282 define_functor_symbol(label, net);
1283 free(label);
1287 * Extend nodes.
1289 void compile_extend_signed(char*label, long wid, struct symb_s arg)
1291 assert(wid >= 0);
1293 vvp_fun_extend_signed*fun = new vvp_fun_extend_signed(wid);
1294 vvp_net_t*ptr = new vvp_net_t;
1295 ptr->fun = fun;
1297 define_functor_symbol(label, ptr);
1298 free(label);
1300 input_connect(ptr, 0, arg.text);
1303 struct __vpiModPath* compile_modpath(char*label, struct symb_s drv,
1304 struct symb_s dest)
1306 vvp_net_t*net = new vvp_net_t;
1307 vvp_fun_modpath*obj = new vvp_fun_modpath(net);
1308 net->fun = obj;
1310 input_connect(net, 0, drv.text);
1312 define_functor_symbol(label, net);
1314 __vpiModPath*modpath = vpip_make_modpath(net);
1316 compile_vpi_lookup(&modpath->path_term_out.expr, dest.text);
1318 free(label);
1320 modpath->modpath = obj;
1321 return modpath;
1324 static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path,
1325 char edge,
1326 struct symb_s src,
1327 struct numbv_s vals,
1328 bool ifnone)
1330 vvp_fun_modpath*dst = path->modpath;
1332 vvp_time64_t use_delay[12];
1333 assert(vals.cnt == 12);
1334 for (unsigned idx = 0 ; idx < vals.cnt ; idx += 1) {
1335 use_delay[idx] = vals.nvec[idx];
1338 numbv_clear(&vals);
1340 vvp_fun_modpath_src*obj = 0;
1342 int vpi_edge = vpiNoEdge;
1343 if (edge == 0) {
1344 obj = new vvp_fun_modpath_src(use_delay);
1346 } else {
1347 bool posedge, negedge;
1348 switch (edge) {
1349 case '+':
1350 vpi_edge = vpiPosedge;
1351 posedge = true;
1352 negedge = false;
1353 break;
1354 case '-':
1355 vpi_edge = vpiNegedge;
1356 posedge = false;
1357 negedge = true;
1358 break;
1359 #if 0
1360 case '*':
1361 posedge = true;
1362 negedge = true;
1363 break;
1364 #endif
1365 default:
1366 fprintf(stderr, "Unknown edge identifier %c(%d).\n", edge,
1367 edge);
1368 assert(0);
1370 obj = new vvp_fun_modpath_edge(use_delay, posedge, negedge);
1373 vvp_net_t*net = new vvp_net_t;
1374 struct __vpiModPathSrc* srcobj = vpip_make_modpath_src (path, use_delay, net) ;
1375 vpip_attach_to_current_scope(vpi_handle(srcobj));
1376 net->fun = obj;
1378 /* Save the vpiEdge directory into the input path term. */
1379 srcobj->path_term_in.edge = vpi_edge;
1380 input_connect(net, 0, src.text);
1381 dst->add_modpath_src(obj, ifnone);
1383 return srcobj;
1386 void compile_modpath_src(struct __vpiModPath*dst, char edge,
1387 struct symb_s src,
1388 struct numbv_s vals,
1389 struct symb_s condit_src,
1390 struct symb_s path_term_in)
1392 struct __vpiModPathSrc*obj =
1393 make_modpath_src(dst, edge, src, vals, false);
1394 input_connect(obj->net, 1, condit_src.text);
1395 compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text);
1398 void compile_modpath_src(struct __vpiModPath*dst, char edge,
1399 struct symb_s src,
1400 struct numbv_s vals,
1401 int condit_src,
1402 struct symb_s path_term_in,
1403 bool ifnone)
1405 assert(condit_src == 0);
1406 struct __vpiModPathSrc*obj =
1407 make_modpath_src(dst, edge, src, vals, ifnone);
1408 compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text);
1412 * A .shift/l statement creates an array of functors for the
1413 * width. The 0 input is the data vector to be shifted and the 1 input
1414 * is the amount of the shift. An unconnected shift amount is set to 0.
1416 void compile_shiftl(char*label, long wid, unsigned argc, struct symb_s*argv)
1418 assert( wid > 0 );
1420 vvp_arith_ *arith = new vvp_shiftl(wid);
1421 make_arith(arith, label, argc, argv);
1424 void compile_shiftr(char*label, long wid, bool signed_flag,
1425 unsigned argc, struct symb_s*argv)
1427 assert( wid > 0 );
1429 vvp_arith_ *arith = new vvp_shiftr(wid, signed_flag);
1430 make_arith(arith, label, argc, argv);
1433 void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
1435 assert(argc <= 4);
1436 vvp_net_fun_t* obj = 0;
1438 if (strcmp(type,"tri") == 0) {
1439 obj = new resolv_functor(vvp_scalar_t(BIT4_Z, 0));
1441 } else if (strncmp(type,"tri$",4) == 0) {
1442 obj = new resolv_functor(vvp_scalar_t(BIT4_Z, 0), strdup(type+4));
1444 } else if (strcmp(type,"tri0") == 0) {
1445 obj = new resolv_functor(vvp_scalar_t(BIT4_0, 5));
1447 } else if (strcmp(type,"tri1") == 0) {
1448 obj = new resolv_functor(vvp_scalar_t(BIT4_1, 5));
1450 } else if (strcmp(type,"triand") == 0) {
1451 obj = new resolv_triand;
1453 } else if (strcmp(type,"trior") == 0) {
1454 obj = new resolv_trior;
1456 } else {
1457 fprintf(stderr, "invalid resolver type: %s\n", type);
1458 compile_errors += 1;
1461 if (obj) {
1462 vvp_net_t*net = new vvp_net_t;
1463 net->fun = obj;
1464 define_functor_symbol(label, net);
1465 inputs_connect(net, argc, argv);
1467 free(type);
1468 free(label);
1469 free(argv);
1472 void compile_udp_def(int sequ, char *label, char *name,
1473 unsigned nin, unsigned init, char **table)
1475 if (sequ) {
1476 vvp_bit4_t init4;
1477 if (init == 0)
1478 init4 = BIT4_0;
1479 else if (init == 1)
1480 init4 = BIT4_1;
1481 else
1482 init4 = BIT4_X;
1484 vvp_udp_seq_s *u = new vvp_udp_seq_s(label, name, nin, init4);
1485 u->compile_table(table);
1486 } else {
1487 vvp_udp_comb_s *u = new vvp_udp_comb_s(label, name, nin);
1488 u->compile_table(table);
1490 free(label);
1493 char **compile_udp_table(char **table, char *row)
1495 if (table)
1496 assert(strlen(*table)==strlen(row));
1498 char **tt;
1499 for (tt = table; tt && *tt; tt++);
1500 int n = (tt-table) + 2;
1502 table = (char**)realloc(table, n*sizeof(char*));
1503 table[n-2] = row;
1504 table[n-1] = 0x0;
1506 return table;
1510 * Take the detailed parse items from a .mem statement and generate
1511 * the necessary internal structures.
1513 * <label> .mem <name>, <msb>, <lsb>, <idxs...> ;
1516 void compile_memory(char *label, char *name, int msb, int lsb,
1517 unsigned narg, long *args)
1519 /* Create an empty memory in the symbol table. */
1520 vvp_memory_t mem = memory_create(label);
1522 assert( narg > 0 && narg%2 == 0 );
1524 struct memory_address_range*ranges
1525 = new struct memory_address_range[narg/2];
1527 for (unsigned idx = 0 ; idx < narg ; idx += 2) {
1528 ranges[idx/2].msb = args[idx+0];
1529 ranges[idx/2].lsb = args[idx+1];
1532 memory_configure(mem, msb, lsb, narg/2, ranges);
1534 delete[]ranges;
1536 vpiHandle obj = vpip_make_memory(mem, name);
1537 compile_vpi_symbol(label, obj);
1538 vpip_attach_to_current_scope(obj);
1540 free(label);
1541 free(name);
1544 void compile_memory_port(char *label, char *memid,
1545 unsigned argc, struct symb_s *argv)
1547 vvp_memory_t mem = memory_find(memid);
1548 free(memid);
1549 assert(mem);
1551 vvp_net_t*ptr = new vvp_net_t;
1552 vvp_fun_memport*fun = new vvp_fun_memport(mem, ptr);
1553 ptr->fun = fun;
1555 define_functor_symbol(label, ptr);
1556 free(label);
1558 inputs_connect(ptr, argc, argv);
1559 free(argv);
1563 * The parser calls this multiple times to parse a .mem/init
1564 * statement. The first call includes a memid label and is used to
1565 * select the memory and the start address. Subsequent calls contain
1566 * only the word value to assign.
1568 void compile_memory_init(char *memid, unsigned i, long val)
1570 static vvp_memory_t current_mem = 0;
1571 static unsigned current_word;
1573 if (memid) {
1574 current_mem = memory_find(memid);
1575 free(memid);
1576 current_word = i;
1577 return;
1580 assert(current_mem);
1582 unsigned word_wid = memory_word_width(current_mem);
1584 vvp_vector4_t val4 (word_wid);
1585 for (unsigned idx = 0 ; idx < word_wid ; idx += 1) {
1586 vvp_bit4_t bit = val & 1 ? BIT4_1 : BIT4_0;
1587 val4.set_bit(idx, bit);
1590 memory_init_word(current_mem, current_word, val4);
1591 current_word += 1;
1595 * The parser uses this function to compile and link an executable
1596 * opcode. I do this by looking up the opcode in the opcode_table. The
1597 * table gives the operand structure that is acceptable, so I can
1598 * process the operands here as well.
1600 void compile_code(char*label, char*mnem, comp_operands_t opa)
1602 /* First, I can give the label a value that is the current
1603 codespace pointer. Don't need the text of the label after
1604 this is done. */
1605 if (label)
1606 compile_codelabel(label);
1608 /* Lookup the opcode in the opcode table. */
1609 struct opcode_table_s*op = (struct opcode_table_s*)
1610 bsearch(mnem, opcode_table, opcode_count,
1611 sizeof(struct opcode_table_s), &opcode_compare);
1612 if (op == 0) {
1613 yyerror("Invalid opcode");
1614 compile_errors += 1;
1615 return;
1618 assert(op);
1620 /* Build up the code from the information about the opcode and
1621 the information from the compiler. */
1622 vvp_code_t code = codespace_allocate();
1623 code->opcode = op->opcode;
1625 if (op->argc != (opa? opa->argc : 0)) {
1626 yyerror("operand count");
1627 compile_errors += 1;
1628 return;
1631 /* Pull the operands that the instruction expects from the
1632 list that the parser supplied. */
1634 for (unsigned idx = 0 ; idx < op->argc ; idx += 1) {
1636 switch (op->argt[idx]) {
1637 case OA_NONE:
1638 break;
1640 case OA_ARR_PTR:
1641 if (opa->argv[idx].ltype != L_SYMB) {
1642 yyerror("operand format");
1643 break;
1646 compile_array_lookup(code, opa->argv[idx].symb.text);
1647 break;
1649 case OA_BIT1:
1650 if (opa->argv[idx].ltype != L_NUMB) {
1651 yyerror("operand format");
1652 break;
1654 code->bit_idx[0] = opa->argv[idx].numb;
1655 break;
1657 case OA_BIT2:
1658 if (opa->argv[idx].ltype != L_NUMB) {
1659 yyerror("operand format");
1660 break;
1662 code->bit_idx[1] = opa->argv[idx].numb;
1663 break;
1665 case OA_CODE_PTR:
1666 if (opa->argv[idx].ltype != L_SYMB) {
1667 yyerror("operand format");
1668 break;
1671 assert(opa->argv[idx].symb.idx == 0);
1672 code_label_lookup(code, opa->argv[idx].symb.text);
1673 break;
1675 case OA_FUNC_PTR:
1676 /* The operand is a functor. Resolve the label to
1677 a functor pointer, or postpone the resolution
1678 if it is not defined yet. */
1679 if (opa->argv[idx].ltype != L_SYMB) {
1680 yyerror("operand format");
1681 break;
1684 functor_ref_lookup(&code->net, opa->argv[idx].symb.text);
1685 break;
1687 case OA_FUNC_PTR2:
1688 /* The operand is a functor. Resolve the label to
1689 a functor pointer, or postpone the resolution
1690 if it is not defined yet. */
1691 if (opa->argv[idx].ltype != L_SYMB) {
1692 yyerror("operand format");
1693 break;
1696 functor_ref_lookup(&code->net2, opa->argv[idx].symb.text);
1697 break;
1699 case OA_NUMBER:
1700 if (opa->argv[idx].ltype != L_NUMB) {
1701 yyerror("operand format");
1702 break;
1705 code->number = opa->argv[idx].numb;
1706 break;
1708 case OA_MEM_PTR:
1709 if (opa->argv[idx].ltype != L_SYMB) {
1710 yyerror("operand format");
1711 break;
1714 compile_mem_lookup(code, opa->argv[idx].symb.text);
1715 break;
1717 case OA_VPI_PTR:
1718 /* The operand is a functor. Resolve the label to
1719 a functor pointer, or postpone the resolution
1720 if it is not defined yet. */
1721 if (opa->argv[idx].ltype != L_SYMB) {
1722 yyerror("operand format");
1723 break;
1726 compile_vpi_lookup(&code->handle, opa->argv[idx].symb.text);
1727 break;
1731 if (opa) free(opa);
1733 free(mnem);
1736 void compile_codelabel(char*label)
1738 symbol_value_t val;
1739 vvp_code_t ptr = codespace_next();
1741 val.ptr = ptr;
1742 sym_set_value(sym_codespace, label, val);
1744 free(label);
1748 void compile_disable(char*label, struct symb_s symb)
1750 if (label)
1751 compile_codelabel(label);
1753 /* Fill in the basics of the %disable in the instruction. */
1754 vvp_code_t code = codespace_allocate();
1755 code->opcode = of_DISABLE;
1757 compile_vpi_lookup(&code->handle, symb.text);
1761 * The %fork instruction is a little different from other instructions
1762 * in that it has an extended field that holds the information needed
1763 * to create the new thread. This includes the target PC and scope.
1764 * I get these from the parser in the form of symbols.
1766 void compile_fork(char*label, struct symb_s dest, struct symb_s scope)
1768 if (label)
1769 compile_codelabel(label);
1772 /* Fill in the basics of the %fork in the instruction. */
1773 vvp_code_t code = codespace_allocate();
1774 code->opcode = of_FORK;
1776 /* Figure out the target PC. */
1777 code_label_lookup(code, dest.text);
1779 /* Figure out the target SCOPE. */
1780 compile_vpi_lookup(&code->handle, scope.text);
1783 void compile_vpi_call(char*label, char*name,
1784 long file_idx, long lineno,
1785 unsigned argc, vpiHandle*argv)
1787 if (label)
1788 compile_codelabel(label);
1790 /* Create an instruction in the code space. */
1791 vvp_code_t code = codespace_allocate();
1792 code->opcode = &of_VPI_CALL;
1794 /* Create a vpiHandle that bundles the call information, and
1795 store that handle in the instruction. */
1796 code->handle = vpip_build_vpi_call(name, 0, 0, 0, argc, argv,
1797 file_idx, lineno);
1798 if (code->handle == 0)
1799 compile_errors += 1;
1801 /* Done with the lexor-allocated name string. */
1802 free(name);
1805 void compile_vpi_func_call(char*label, char*name,
1806 unsigned vbit, int vwid,
1807 long file_idx, long lineno,
1808 unsigned argc, vpiHandle*argv)
1810 if (label)
1811 compile_codelabel(label);
1813 /* Create an instruction in the code space. */
1814 vvp_code_t code = codespace_allocate();
1815 code->opcode = &of_VPI_CALL;
1817 /* Create a vpiHandle that bundles the call information, and
1818 store that handle in the instruction. */
1819 code->handle = vpip_build_vpi_call(name, vbit, vwid, 0, argc, argv,
1820 file_idx, lineno);
1821 if (code->handle == 0)
1822 compile_errors += 1;
1824 /* Done with the lexor-allocated name string. */
1825 free(name);
1829 * When the parser finds a thread statement, I create a new thread
1830 * with the start address referenced by the program symbol passed to
1831 * me.
1833 void compile_thread(char*start_sym, char*flag)
1835 bool push_flag = false;
1837 symbol_value_t tmp = sym_get_value(sym_codespace, start_sym);
1838 vvp_code_t pc = reinterpret_cast<vvp_code_t>(tmp.ptr);
1839 if (pc == 0) {
1840 yyerror("unresolved address");
1841 return;
1844 if (flag && (strcmp(flag,"$push") == 0))
1845 push_flag = true;
1847 vthread_t thr = vthread_new(pc, vpip_peek_current_scope());
1848 schedule_vthread(thr, 0, push_flag);
1850 free(start_sym);
1851 if (flag != 0)
1852 free(flag);
1855 void compile_param_logic(char*label, char*name, char*value, bool signed_flag,
1856 long file_idx, long lineno)
1858 vvp_vector4_t value4 = c4string_to_vector4(value);
1859 vpiHandle obj = vpip_make_binary_param(name, value4, signed_flag,
1860 file_idx, lineno);
1861 compile_vpi_symbol(label, obj);
1862 vpip_attach_to_current_scope(obj);
1864 free(label);
1865 free(value);
1868 void compile_param_string(char*label, char*name, char*value,
1869 long file_idx, long lineno)
1871 vpiHandle obj = vpip_make_string_param(name, value, file_idx, lineno);
1872 compile_vpi_symbol(label, obj);
1873 vpip_attach_to_current_scope(obj);
1875 free(label);
1878 void compile_param_real(char*label, char*name, char*value,
1879 long file_idx, long lineno)
1881 double dvalue = crstring_to_double(value);
1882 vpiHandle obj = vpip_make_real_param(name, dvalue, file_idx, lineno);
1883 compile_vpi_symbol(label, obj);
1884 vpip_attach_to_current_scope(obj);
1886 free(label);
1887 free(value);