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)
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
28 # include "schedule.h"
29 # include "vpi_priv.h"
30 # include "parse_misc.h"
31 # include "statistics.h"
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.
55 /* Place holder for unused operand */
57 /* The operand is a number, an immediate unsigned integer */
59 /* The operand is a pointer to an array. */
61 /* The operand is a thread bit index or short integer */
64 /* The operand is a pointer to code space */
66 /* The operand is a variable or net pointer */
68 /* The operand is a second functor pointer */
70 /* The operand is a pointer to a memory */
72 /* The operand is a VPI handle */
76 struct opcode_table_s
{
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
)
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
);
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
;
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
268 symbol_value_t val
= sym_get_value(sym_vpi
, label
);
270 vpiHandle vpi
= (vpiHandle
) val
.ptr
;
271 switch (vpi
->vpi_type
->type_code
) {
274 case vpiIntegerVar
: {
275 __vpiSignal
*sig
= (__vpiSignal
*)vpi
;
280 __vpiRealVar
*sig
= (__vpiRealVar
*)vpi
;
284 case vpiNamedEvent
: {
285 __vpiNamedEvent
*tmp
= (__vpiNamedEvent
*)vpi
;
290 fprintf(stderr
, "Unsupported type %d.\n",
291 vpi
->vpi_type
->type_code
);
297 /* Failing that, look for a general functor. */
298 vvp_net_t
*tmp
= lookup_functor_symbol(label
);
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()) {
336 cur
->next
= resolv_list
;
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
{
350 // port to be driven by the located node.
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
);
360 // Link the input port to the located output.
361 vvp_net_t
*net
= port
.ptr();
362 net
->port
[port
.port()] = tmp
->out
;
370 fprintf(stderr
, "unresolved vvp_net reference: %s\n", source
);
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
;
388 * Generic functor reference lookup.
391 struct functor_gen_resolv_list_s
: public resolv_list_s
{
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
);
409 fprintf(stderr
, "unresolved functor reference: %s\n", source
);
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
;
429 struct vpi_handle_resolv_list_s
: public resolv_list_s
{
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
);
439 // check for thread vector T<base,wid>
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
,
450 && n
== strlen(label
)) {
452 bool signed_flag
= false;
453 for (char*fp
= ss
; *fp
; fp
+= 1) switch (*fp
) {
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
);
477 // check for memory word M<mem,base,wid>
481 *handle
= (vpiHandle
) val
.ptr
;
487 fprintf(stderr
, "unresolved vpi name lookup: %s\n", label
);
492 void compile_vpi_lookup(vpiHandle
*handle
, char*label
)
494 if (strcmp(label
, "$time") == 0) {
495 *handle
= vpip_sim_time(vpip_peek_current_scope());
500 if (strcmp(label
, "$stime") == 0) {
501 *handle
= vpip_sim_time(vpip_peek_current_scope());
506 if (strcmp(label
, "$realtime") == 0) {
507 *handle
= vpip_sim_realtime(vpip_peek_current_scope());
512 if (strcmp(label
, "$simtime") == 0) {
513 *handle
= vpip_sim_time(0);
518 struct vpi_handle_resolv_list_s
*res
519 = new struct vpi_handle_resolv_list_s
;
521 res
->handle
= handle
;
530 struct code_label_resolv_list_s
: public resolv_list_s
{
531 struct vvp_code_s
*code
;
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
);
540 if (code
->opcode
== of_FORK
)
541 code
->cptr2
= reinterpret_cast<vvp_code_t
>(val
.ptr
);
543 code
->cptr
= reinterpret_cast<vvp_code_t
>(val
.ptr
);
550 "unresolved code label: %s\n",
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
;
570 struct memory_resolv_list_s
: public resolv_list_s
{
571 struct vvp_code_s
*code
;
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) {
585 fprintf(stderr
, "Memory unresolved: %s\n", label
);
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
;
601 struct array_resolv_list_s
: public resolv_list_s
{
602 struct vvp_code_s
*code
;
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) {
616 fprintf(stderr
, "Array unresolved: %s\n", label
);
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
;
632 static list
<struct __vpiSysTaskCall
*> scheduled_compiletf
;
634 void compile_compiletf(struct __vpiSysTaskCall
*obj
)
636 if (obj
->defn
->info
.compiletf
== 0)
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)
654 fprintf(stderr
, " ... Linking\n");
659 struct resolv_list_s
*res
= resolv_list
;
661 last
= nerrs
== lnerrs
;
665 struct resolv_list_s
*cur
= res
;
667 if (cur
->resolve(last
))
671 cur
->next
= resolv_list
;
677 "compile_cleanup: %d unresolved items\n",
679 } while (nerrs
&& !last
);
681 compile_errors
+= nerrs
;
684 fprintf(stderr
, " ... Removing symbol tables\n");
688 /* After compile is complete, the vpi symbol table is no
689 longer needed. VPI objects are located by following
691 delete_symbol_table(sym_vpi
);
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
);
699 delete_symbol_table(sym_functors
);
703 fprintf(stderr
, " ... Compiletf functions\n");
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();
714 obj
->defn
->info
.compiletf (obj
->defn
->info
.user_data
);
718 vpi_mode_flag
= VPI_MODE_NONE
;
721 void compile_vpi_symbol(const char*label
, vpiHandle 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();
742 void compile_load_vpi_module(char*name
)
744 vpip_load_module(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
)
772 uint64_t mant
= strtoull(cp
, &cp
, 16);
775 int exp
= strtoul(cp
, 0, 16);
778 if (mant
== 0 && exp
== 0x3fff) {
780 } else if (mant
== 0 && exp
== 0x7fff) {
782 } else if (exp
== 0x3fff) {
785 double sign
= (exp
& 0x4000)? -1.0 : 1.0;
788 tmp
= sign
* ldexp((double)mant
, exp
- 0x1000);
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
);
813 /* Is this a vvp_vector4_t constant value? */
814 if ((strncmp(label
, "C4<", 3) == 0)
815 && ((tp
= strchr(label
,'>')))
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
);
834 /* Is this a vvp_vector8_t constant value? */
835 if ((strncmp(label
, "C8<", 3) == 0)
836 && ((tp
= strchr(label
,'>')))
838 && (strspn(label
+3, "01234567xz")+3 == (unsigned)(tp
-label
))) {
840 size_t vsize
= tp
-label
-3;
841 assert(vsize
%3 == 0);
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]) {
866 tmp
.set_bit(vsize
-idx
-1, vvp_scalar_t(bit
, dr0
, dr1
));
869 schedule_set_vector(ifdx
, tmp
);
875 /* Handle the Cr<> constant driver, which is a real-value
877 if ((strncmp(label
, "Cr<", 3) == 0)
878 && ((tp
= strchr(label
,'>')))
880 && (strspn(label
+3, "0123456789abcdefmg")+3 == (unsigned)(tp
-label
))) {
882 double tmp
= crstring_to_double(label
);
884 schedule_set_vector(ifdx
, tmp
);
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
893 postpone_functor_input(ifdx
, label
);
896 void inputs_connect(vvp_net_t
*fdx
, unsigned argc
, struct symb_s
*argv
)
899 cerr
<< "XXXX argv[0] = " << argv
[0].text
<< endl
;
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;
918 if (base
+trans
> argc
)
921 vvp_wide_fun_t
*cur
= new vvp_wide_fun_t(core
, base
);
922 vvp_net_t
*ptr
= new vvp_net_t
;
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
;
935 define_functor_symbol(label
, ptr
);
939 inputs_connect(ptr
, argc
, argv
);
944 void compile_arith_div(char*label
, long wid
, bool signed_flag
,
945 unsigned argc
, struct symb_s
*argv
)
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
);
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
)
965 fprintf(stderr
, "%s; .arith/divr has wrong number of symbols\n", label
);
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
)
980 fprintf(stderr
, "%s .arith/mod has wrong number of symbols\n", label
);
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
)
993 fprintf(stderr
, "%s .arith/mod.r has wrong number of symbols\n", label
);
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
)
1008 fprintf(stderr
, "%s .arith/mult has wrong number of symbols\n", label
);
1009 compile_errors
+= 1;
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
)
1020 fprintf(stderr
, "%s .arith/mult.r has wrong number of symbols\n", label
);
1021 compile_errors
+= 1;
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
)
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. */
1037 assert( wid
<= (long)(8*sizeof(long)) );
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;
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
)
1056 fprintf(stderr
, "%s .arith/pow.r has wrong number of symbols\n", label
);
1057 compile_errors
+= 1;
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
)
1070 fprintf(stderr
, "%s .arith/sub has wrong number of symbols\n", label
);
1071 compile_errors
+= 1;
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
)
1082 fprintf(stderr
, "%s; .arith/sub.r has wrong number of symbols\n", label
);
1083 compile_errors
+= 1;
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
)
1096 fprintf(stderr
, "%s .arith/sum has wrong number of symbols\n", label
);
1097 compile_errors
+= 1;
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
)
1108 fprintf(stderr
, "%s .arith/sum.r has wrong number of symbols\n", label
);
1109 compile_errors
+= 1;
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
)
1123 fprintf(stderr
, "%s .cmp/eeq has wrong number of symbols\n",label
);
1124 compile_errors
+= 1;
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
)
1139 fprintf(stderr
, "%s .cmp/eeq has wrong number of symbols\n",label
);
1140 compile_errors
+= 1;
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
)
1154 fprintf(stderr
, "%s .cmp/eq has wrong number of symbols\n",label
);
1155 compile_errors
+= 1;
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
)
1166 fprintf(stderr
, "%s .cmp/eq.r has wrong number of symbols\n",label
);
1167 compile_errors
+= 1;
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
)
1180 fprintf(stderr
, "%s .cmp/ne has wrong number of symbols\n",label
);
1181 compile_errors
+= 1;
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
)
1192 fprintf(stderr
, "%s .cmp/ne.r has wrong number of symbols\n",label
);
1193 compile_errors
+= 1;
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
)
1207 fprintf(stderr
, "%s .cmp/ge has wrong number of symbols\n", label
);
1208 compile_errors
+= 1;
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
)
1220 fprintf(stderr
, "%s .cmp/ge.r has wrong number of symbols\n",label
);
1221 compile_errors
+= 1;
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
)
1235 fprintf(stderr
, "%s .cmp/gt has wrong number of symbols\n", label
);
1236 compile_errors
+= 1;
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
)
1248 fprintf(stderr
, "%s .cmp/gt.r has wrong number of symbols\n",label
);
1249 compile_errors
+= 1;
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
);
1266 input_connect(net
, 0, arg
.text
);
1268 define_functor_symbol(label
, net
);
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
);
1279 inputs_connect(net
, argc
, argv
);
1282 define_functor_symbol(label
, net
);
1289 void compile_extend_signed(char*label
, long wid
, struct symb_s arg
)
1293 vvp_fun_extend_signed
*fun
= new vvp_fun_extend_signed(wid
);
1294 vvp_net_t
*ptr
= new vvp_net_t
;
1297 define_functor_symbol(label
, ptr
);
1300 input_connect(ptr
, 0, arg
.text
);
1303 struct __vpiModPath
* compile_modpath(char*label
, struct symb_s drv
,
1306 vvp_net_t
*net
= new vvp_net_t
;
1307 vvp_fun_modpath
*obj
= new vvp_fun_modpath(net
);
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
);
1320 modpath
->modpath
= obj
;
1324 static struct __vpiModPathSrc
*make_modpath_src(struct __vpiModPath
*path
,
1327 struct numbv_s vals
,
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
];
1340 vvp_fun_modpath_src
*obj
= 0;
1342 int vpi_edge
= vpiNoEdge
;
1344 obj
= new vvp_fun_modpath_src(use_delay
);
1347 bool posedge
, negedge
;
1350 vpi_edge
= vpiPosedge
;
1355 vpi_edge
= vpiNegedge
;
1366 fprintf(stderr
, "Unknown edge identifier %c(%d).\n", edge
,
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
));
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
);
1386 void compile_modpath_src(struct __vpiModPath
*dst
, char edge
,
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
,
1400 struct numbv_s vals
,
1402 struct symb_s path_term_in
,
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
)
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
)
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
)
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
;
1457 fprintf(stderr
, "invalid resolver type: %s\n", type
);
1458 compile_errors
+= 1;
1462 vvp_net_t
*net
= new vvp_net_t
;
1464 define_functor_symbol(label
, net
);
1465 inputs_connect(net
, argc
, argv
);
1472 void compile_udp_def(int sequ
, char *label
, char *name
,
1473 unsigned nin
, unsigned init
, char **table
)
1484 vvp_udp_seq_s
*u
= new vvp_udp_seq_s(label
, name
, nin
, init4
);
1485 u
->compile_table(table
);
1487 vvp_udp_comb_s
*u
= new vvp_udp_comb_s(label
, name
, nin
);
1488 u
->compile_table(table
);
1493 char **compile_udp_table(char **table
, char *row
)
1496 assert(strlen(*table
)==strlen(row
));
1499 for (tt
= table
; tt
&& *tt
; tt
++);
1500 int n
= (tt
-table
) + 2;
1502 table
= (char**)realloc(table
, n
*sizeof(char*));
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
);
1536 vpiHandle obj
= vpip_make_memory(mem
, name
);
1537 compile_vpi_symbol(label
, obj
);
1538 vpip_attach_to_current_scope(obj
);
1544 void compile_memory_port(char *label
, char *memid
,
1545 unsigned argc
, struct symb_s
*argv
)
1547 vvp_memory_t mem
= memory_find(memid
);
1551 vvp_net_t
*ptr
= new vvp_net_t
;
1552 vvp_fun_memport
*fun
= new vvp_fun_memport(mem
, ptr
);
1555 define_functor_symbol(label
, ptr
);
1558 inputs_connect(ptr
, argc
, 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
;
1574 current_mem
= memory_find(memid
);
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
);
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
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
);
1613 yyerror("Invalid opcode");
1614 compile_errors
+= 1;
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;
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
]) {
1641 if (opa
->argv
[idx
].ltype
!= L_SYMB
) {
1642 yyerror("operand format");
1646 compile_array_lookup(code
, opa
->argv
[idx
].symb
.text
);
1650 if (opa
->argv
[idx
].ltype
!= L_NUMB
) {
1651 yyerror("operand format");
1654 code
->bit_idx
[0] = opa
->argv
[idx
].numb
;
1658 if (opa
->argv
[idx
].ltype
!= L_NUMB
) {
1659 yyerror("operand format");
1662 code
->bit_idx
[1] = opa
->argv
[idx
].numb
;
1666 if (opa
->argv
[idx
].ltype
!= L_SYMB
) {
1667 yyerror("operand format");
1671 assert(opa
->argv
[idx
].symb
.idx
== 0);
1672 code_label_lookup(code
, opa
->argv
[idx
].symb
.text
);
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");
1684 functor_ref_lookup(&code
->net
, opa
->argv
[idx
].symb
.text
);
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");
1696 functor_ref_lookup(&code
->net2
, opa
->argv
[idx
].symb
.text
);
1700 if (opa
->argv
[idx
].ltype
!= L_NUMB
) {
1701 yyerror("operand format");
1705 code
->number
= opa
->argv
[idx
].numb
;
1709 if (opa
->argv
[idx
].ltype
!= L_SYMB
) {
1710 yyerror("operand format");
1714 compile_mem_lookup(code
, opa
->argv
[idx
].symb
.text
);
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");
1726 compile_vpi_lookup(&code
->handle
, opa
->argv
[idx
].symb
.text
);
1736 void compile_codelabel(char*label
)
1739 vvp_code_t ptr
= codespace_next();
1742 sym_set_value(sym_codespace
, label
, val
);
1748 void compile_disable(char*label
, struct symb_s symb
)
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
)
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
)
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
,
1798 if (code
->handle
== 0)
1799 compile_errors
+= 1;
1801 /* Done with the lexor-allocated name string. */
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
)
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
,
1821 if (code
->handle
== 0)
1822 compile_errors
+= 1;
1824 /* Done with the lexor-allocated name string. */
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
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
);
1840 yyerror("unresolved address");
1844 if (flag
&& (strcmp(flag
,"$push") == 0))
1847 vthread_t thr
= vthread_new(pc
, vpip_peek_current_scope());
1848 schedule_vthread(thr
, 0, push_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
,
1861 compile_vpi_symbol(label
, obj
);
1862 vpip_attach_to_current_scope(obj
);
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
);
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
);