2001-03-11 01:29:38 +01:00
|
|
|
/*
|
2021-02-20 08:21:12 +01:00
|
|
|
* Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
|
2001-03-11 01:29:38 +01:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2001-03-11 01:29:38 +01:00
|
|
|
*/
|
|
|
|
|
|
2012-06-04 21:43:33 +02:00
|
|
|
|
|
|
|
|
# include "config.h"
|
|
|
|
|
# include "delay.h"
|
2001-06-05 05:05:41 +02:00
|
|
|
# include "arith.h"
|
2001-03-11 01:29:38 +01:00
|
|
|
# include "compile.h"
|
2003-07-30 03:13:28 +02:00
|
|
|
# include "logic.h"
|
2001-05-09 04:53:25 +02:00
|
|
|
# include "resolv.h"
|
2004-10-04 03:10:51 +02:00
|
|
|
# include "udp.h"
|
2001-03-11 01:29:38 +01:00
|
|
|
# include "symbols.h"
|
|
|
|
|
# include "codes.h"
|
|
|
|
|
# include "schedule.h"
|
2001-03-16 02:44:34 +01:00
|
|
|
# include "vpi_priv.h"
|
2001-03-11 01:29:38 +01:00
|
|
|
# include "parse_misc.h"
|
2002-07-05 22:08:44 +02:00
|
|
|
# include "statistics.h"
|
2012-06-04 21:43:33 +02:00
|
|
|
# include "schedule.h"
|
2005-06-14 02:42:06 +02:00
|
|
|
# include <iostream>
|
2007-07-25 03:24:24 +02:00
|
|
|
# include <list>
|
2010-05-31 22:12:06 +02:00
|
|
|
# include <cstdlib>
|
|
|
|
|
# include <cstring>
|
|
|
|
|
# include <cassert>
|
2001-03-11 01:29:38 +01:00
|
|
|
|
2001-05-22 04:14:47 +02:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-10-24 00:52:56 +02:00
|
|
|
# include "ivl_alloc.h"
|
|
|
|
|
|
2001-03-22 23:38:13 +01:00
|
|
|
unsigned compile_errors = 0;
|
2001-03-11 01:29:38 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The opcode table lists all the code mnemonics, along with their
|
|
|
|
|
* opcode and operand types. The table is written sorted by mnemonic
|
|
|
|
|
* so that it can be searched by binary search. The opcode_compare
|
|
|
|
|
* function is a helper function for that lookup.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
enum operand_e {
|
|
|
|
|
/* Place holder for unused operand */
|
|
|
|
|
OA_NONE,
|
2001-03-12 00:06:49 +01:00
|
|
|
/* The operand is a number, an immediate unsigned integer */
|
2001-03-11 01:29:38 +01:00
|
|
|
OA_NUMBER,
|
2007-01-16 06:44:14 +01:00
|
|
|
/* The operand is a pointer to an array. */
|
|
|
|
|
OA_ARR_PTR,
|
2001-11-01 04:00:19 +01:00
|
|
|
/* The operand is a thread bit index or short integer */
|
2001-03-12 00:06:49 +01:00
|
|
|
OA_BIT1,
|
|
|
|
|
OA_BIT2,
|
2001-03-11 01:29:38 +01:00
|
|
|
/* The operand is a pointer to code space */
|
|
|
|
|
OA_CODE_PTR,
|
2015-12-27 22:07:42 +01:00
|
|
|
OA_CODE_PTR2,
|
2001-03-11 01:29:38 +01:00
|
|
|
/* The operand is a variable or net pointer */
|
2001-05-01 03:09:39 +02:00
|
|
|
OA_FUNC_PTR,
|
2008-09-04 18:41:51 +02:00
|
|
|
/* The operand is a second functor pointer */
|
2001-11-01 04:00:19 +01:00
|
|
|
OA_FUNC_PTR2,
|
2002-08-28 19:15:06 +02:00
|
|
|
/* The operand is a VPI handle */
|
2012-06-18 03:43:25 +02:00
|
|
|
OA_VPI_PTR,
|
|
|
|
|
/* String */
|
|
|
|
|
OA_STRING
|
2001-03-11 01:29:38 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct opcode_table_s {
|
|
|
|
|
const char*mnemonic;
|
|
|
|
|
vvp_code_fun opcode;
|
|
|
|
|
|
|
|
|
|
unsigned argc;
|
|
|
|
|
enum operand_e argt[OPERAND_MAX];
|
|
|
|
|
};
|
|
|
|
|
|
2010-10-24 00:52:56 +02:00
|
|
|
static const struct opcode_table_s opcode_table[] = {
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%abs/wr", of_ABS_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%add", of_ADD, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%add/wr", of_ADD_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-11-18 21:27:55 +01:00
|
|
|
{ "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
2008-10-28 18:52:39 +01:00
|
|
|
{ "%alloc", of_ALLOC, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%and", of_AND, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-05 23:12:27 +01:00
|
|
|
{ "%and/r", of_ANDR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%assign/ar",of_ASSIGN_AR,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%assign/ar/d",of_ASSIGN_ARD,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%assign/ar/e",of_ASSIGN_ARE,1,{OA_ARR_PTR,OA_NONE, OA_NONE} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%assign/vec4", of_ASSIGN_VEC4, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%assign/vec4/a/d", of_ASSIGN_VEC4_A_D, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
2014-01-24 03:39:29 +01:00
|
|
|
{ "%assign/vec4/a/e", of_ASSIGN_VEC4_A_E, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%assign/vec4/d", of_ASSIGN_VEC4D, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%assign/vec4/e", of_ASSIGN_VEC4E, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%assign/vec4/off/d",of_ASSIGN_VEC4_OFF_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
2014-01-24 03:39:29 +01:00
|
|
|
{ "%assign/vec4/off/e",of_ASSIGN_VEC4_OFF_E, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%assign/wr", of_ASSIGN_WR, 2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%assign/wr/d",of_ASSIGN_WRD,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%assign/wr/e",of_ASSIGN_WRE,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%blend", of_BLEND, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%blend/wr", of_BLEND_WR,0, {OA_NONE, OA_NONE, OA_NONE} },
|
2001-05-06 01:55:46 +02:00
|
|
|
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2015-12-28 05:29:10 +01:00
|
|
|
{ "%callf/obj", of_CALLF_OBJ, 2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
|
|
|
|
|
{ "%callf/real", of_CALLF_REAL, 2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
|
|
|
|
|
{ "%callf/str", of_CALLF_STR, 2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
|
|
|
|
|
{ "%callf/vec4", of_CALLF_VEC4, 2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
|
|
|
|
|
{ "%callf/void", of_CALLF_VOID, 2,{OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
|
2014-01-04 23:58:58 +01:00
|
|
|
{ "%cassign/link", of_CASSIGN_LINK, 2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
|
|
|
|
|
{ "%cassign/vec4", of_CASSIGN_VEC4, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cassign/vec4/off",of_CASSIGN_VEC4_OFF,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%cassign/wr", of_CASSIGN_WR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
2019-09-11 22:56:27 +02:00
|
|
|
{ "%cast/vec2/dar", of_CAST_VEC2_DAR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cast/vec4/dar", of_CAST_VEC4_DAR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2019-09-09 22:39:35 +02:00
|
|
|
{ "%cast/vec4/str", of_CAST_VEC4_STR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2017-11-18 04:32:09 +01:00
|
|
|
{ "%cast2", of_CAST2, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/e", of_CMPE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/ne", of_CMPNE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/str", of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/u", of_CMPU, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/we", of_CMPWE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/wne", of_CMPWNE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/x", of_CMPX, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmp/z", of_CMPZ, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cmpi/e", of_CMPIE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
|
|
|
|
{ "%cmpi/ne", of_CMPINE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
|
|
|
|
{ "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
|
|
|
|
{ "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
2014-11-18 21:27:55 +01:00
|
|
|
{ "%concat/str", of_CONCAT_STR, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%concat/vec4", of_CONCAT_VEC4, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%concati/str", of_CONCATI_STR, 1,{OA_STRING,OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%concati/vec4",of_CONCATI_VEC4,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
|
2014-01-21 21:02:59 +01:00
|
|
|
{ "%cvt/rv", of_CVT_RV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cvt/rv/s", of_CVT_RV_S,0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%cvt/sr", of_CVT_SR, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%cvt/ur", of_CVT_UR, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
2014-01-05 23:12:27 +01:00
|
|
|
{ "%cvt/vr", of_CVT_VR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2008-04-10 03:56:42 +02:00
|
|
|
{ "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
2008-04-17 01:11:23 +02:00
|
|
|
{ "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
2014-02-08 01:10:28 +01:00
|
|
|
{ "%debug/thr", of_DEBUG_THR, 1,{OA_STRING, OA_NONE, OA_NONE} },
|
2006-08-08 07:11:37 +02:00
|
|
|
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
2001-07-19 06:40:55 +02:00
|
|
|
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2020-07-25 09:48:57 +02:00
|
|
|
{ "%delete/elem",of_DELETE_ELEM,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
2012-07-17 03:15:29 +02:00
|
|
|
{ "%delete/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
2020-08-03 08:34:52 +02:00
|
|
|
{ "%delete/tail",of_DELETE_TAIL,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
2015-12-27 22:07:42 +01:00
|
|
|
{ "%disable", of_DISABLE, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
|
2022-04-11 17:40:03 +02:00
|
|
|
{ "%disable/flow", of_DISABLE_FLOW, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
|
2013-10-18 00:09:31 +02:00
|
|
|
{ "%disable/fork",of_DISABLE_FORK,0,{OA_NONE,OA_NONE, OA_NONE} },
|
2014-01-06 19:14:49 +01:00
|
|
|
{ "%div", of_DIV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%div/s", of_DIV_S, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%div/wr", of_DIV_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2020-11-26 21:35:16 +01:00
|
|
|
{ "%dup/obj", of_DUP_OBJ, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%dup/real", of_DUP_REAL,0, {OA_NONE, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%dup/vec4", of_DUP_VEC4,0, {OA_NONE, OA_NONE, OA_NONE} },
|
2001-03-22 06:08:00 +01:00
|
|
|
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2008-09-11 04:37:11 +02:00
|
|
|
{ "%evctl", of_EVCTL, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
2008-09-18 02:49:45 +02:00
|
|
|
{ "%evctl/c",of_EVCTLC, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2008-09-11 04:37:11 +02:00
|
|
|
{ "%evctl/i",of_EVCTLI, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%evctl/s",of_EVCTLS, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
2021-02-20 08:21:12 +01:00
|
|
|
{ "%event", of_EVENT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%event/nb", of_EVENT_NB, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2014-11-20 23:47:44 +01:00
|
|
|
{ "%flag_inv", of_FLAG_INV, 1, {OA_BIT1, OA_NONE, OA_NONE} },
|
2014-01-14 21:00:39 +01:00
|
|
|
{ "%flag_mov", of_FLAG_MOV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
|
|
|
|
{ "%flag_or", of_FLAG_OR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%flag_set/imm", of_FLAG_SET_IMM, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%flag_set/vec4", of_FLAG_SET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2014-01-14 03:57:03 +01:00
|
|
|
{ "%force/link", of_FORCE_LINK,2,{OA_FUNC_PTR, OA_FUNC_PTR2, OA_NONE} },
|
|
|
|
|
{ "%force/vec4", of_FORCE_VEC4, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%force/vec4/off",of_FORCE_VEC4_OFF,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
2016-05-10 23:16:40 +02:00
|
|
|
{ "%force/vec4/off/d",of_FORCE_VEC4_OFF_D,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
2014-01-14 03:57:03 +01:00
|
|
|
{ "%force/wr", of_FORCE_WR, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
2015-12-27 22:07:42 +01:00
|
|
|
{ "%fork", of_FORK, 2, {OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
|
2008-10-28 18:52:39 +01:00
|
|
|
{ "%free", of_FREE, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%inv", of_INV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2009-02-17 01:44:52 +01:00
|
|
|
{ "%ix/add", of_IX_ADD, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
2007-12-08 02:28:58 +01:00
|
|
|
{ "%ix/getv",of_IX_GETV,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
2009-12-19 19:00:08 +01:00
|
|
|
{ "%ix/getv/s",of_IX_GETV_S,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
2009-02-17 01:44:52 +01:00
|
|
|
{ "%ix/load",of_IX_LOAD,3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
2013-07-31 08:20:37 +02:00
|
|
|
{ "%ix/mov", of_IX_MOV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
2009-02-17 01:44:52 +01:00
|
|
|
{ "%ix/mul", of_IX_MUL, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
|
|
|
|
{ "%ix/sub", of_IX_SUB, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%ix/vec4", of_IX_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%ix/vec4/s",of_IX_VEC4_S,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2001-03-22 06:08:00 +01:00
|
|
|
{ "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
2001-03-25 05:54:26 +02:00
|
|
|
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
2001-03-31 19:36:02 +02:00
|
|
|
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%jmp/1xz",of_JMP1XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
2001-03-30 06:55:22 +02:00
|
|
|
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-05-20 20:39:52 +02:00
|
|
|
{ "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%load/ar",of_LOAD_AR,2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
2014-02-07 00:05:26 +01:00
|
|
|
{ "%load/dar/r", of_LOAD_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE}},
|
|
|
|
|
{ "%load/dar/str",of_LOAD_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%load/dar/vec4",of_LOAD_DAR_VEC4,1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
2014-10-21 18:12:02 +02:00
|
|
|
{ "%load/obja", of_LOAD_OBJA, 2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%load/real", of_LOAD_REAL, 1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%load/stra", of_LOAD_STRA, 2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%load/vec4", of_LOAD_VEC4, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%load/vec4a", of_LOAD_VEC4A,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%max/wr", of_MAX_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%min/wr", of_MIN_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-06 19:14:49 +01:00
|
|
|
{ "%mod", of_MOD, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-04 23:06:58 +01:00
|
|
|
{ "%mod/s", of_MOD_S, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%mod/wr", of_MOD_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-04 23:06:58 +01:00
|
|
|
{ "%mul", of_MUL, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%mul/wr", of_MUL_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-12-02 21:46:17 +01:00
|
|
|
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
2014-01-05 00:48:16 +01:00
|
|
|
{ "%nand", of_NAND, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-05 23:12:27 +01:00
|
|
|
{ "%nand/r", of_NANDR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-12-10 02:59:16 +01:00
|
|
|
{ "%new/cobj", of_NEW_COBJ, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%new/darray",of_NEW_DARRAY,2, {OA_BIT1, OA_STRING,OA_NONE} },
|
2001-04-01 08:12:13 +02:00
|
|
|
{ "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-05 00:48:16 +01:00
|
|
|
{ "%nor", of_NOR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-04 23:06:58 +01:00
|
|
|
{ "%nor/r", of_NORR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-11-22 02:48:46 +01:00
|
|
|
{ "%null", of_NULL, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%or", of_OR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-05 23:12:27 +01:00
|
|
|
{ "%or/r", of_ORR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%pad/s", of_PAD_S, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%pad/u", of_PAD_U, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%part/s", of_PART_S, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%part/u", of_PART_U, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2014-11-21 03:43:24 +01:00
|
|
|
{ "%parti/s",of_PARTI_S,3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
|
|
|
|
{ "%parti/u",of_PARTI_U,3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
2013-11-23 04:54:42 +01:00
|
|
|
{ "%pop/obj", of_POP_OBJ, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%pop/real",of_POP_REAL,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%pop/str", of_POP_STR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%pop/vec4",of_POP_VEC4,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2014-01-06 19:34:07 +01:00
|
|
|
{ "%pow", of_POW, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%pow/s", of_POW_S, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%pow/wr", of_POW_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-10-22 21:58:50 +02:00
|
|
|
{ "%prop/obj",of_PROP_OBJ,2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
2013-01-14 02:14:40 +01:00
|
|
|
{ "%prop/r", of_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%prop/str",of_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2014-02-07 20:24:41 +01:00
|
|
|
{ "%prop/v", of_PROP_V, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%pushi/real",of_PUSHI_REAL,2,{OA_BIT1, OA_BIT2, OA_NONE} },
|
|
|
|
|
{ "%pushi/str", of_PUSHI_STR, 1,{OA_STRING, OA_NONE, OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%pushi/vec4",of_PUSHI_VEC4,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
|
2014-10-24 19:16:35 +02:00
|
|
|
{ "%pushv/str", of_PUSHV_STR, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
2014-02-01 04:01:28 +01:00
|
|
|
{ "%putc/str/vec4",of_PUTC_STR_VEC4,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
2020-07-30 07:59:16 +02:00
|
|
|
{ "%qinsert/real",of_QINSERT_REAL,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
|
|
|
|
{ "%qinsert/str", of_QINSERT_STR, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
|
|
|
|
{ "%qinsert/v", of_QINSERT_V, 3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
2020-07-20 06:34:04 +02:00
|
|
|
{ "%qpop/b/real",of_QPOP_B_REAL,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
|
|
|
|
{ "%qpop/b/str", of_QPOP_B_STR, 1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
2020-07-24 04:10:38 +02:00
|
|
|
{ "%qpop/b/v", of_QPOP_B_V, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
2020-07-20 06:34:04 +02:00
|
|
|
{ "%qpop/f/real",of_QPOP_F_REAL,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
|
|
|
|
{ "%qpop/f/str", of_QPOP_F_STR, 1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
2020-07-24 04:10:38 +02:00
|
|
|
{ "%qpop/f/v", of_QPOP_F_V, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
2008-03-12 00:04:00 +01:00
|
|
|
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
|
|
|
|
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%release/wr", of_RELEASE_WR, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
|
|
|
|
{ "%replicate", of_REPLICATE, 1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
2016-01-11 02:09:33 +01:00
|
|
|
{ "%ret/real", of_RET_REAL, 1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
2016-03-02 00:38:28 +01:00
|
|
|
{ "%ret/str", of_RET_STR, 1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
2016-02-01 00:29:52 +01:00
|
|
|
{ "%ret/vec4", of_RET_VEC4, 3,{OA_NUMBER, OA_BIT1,OA_BIT2} },
|
2016-01-25 03:36:26 +01:00
|
|
|
{ "%retload/real",of_RETLOAD_REAL,1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
2016-03-02 00:38:28 +01:00
|
|
|
{ "%retload/str", of_RETLOAD_STR, 1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
2016-01-25 03:36:26 +01:00
|
|
|
{ "%retload/vec4",of_RETLOAD_VEC4,1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
2013-04-28 19:10:36 +02:00
|
|
|
{ "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2013-10-19 03:32:56 +02:00
|
|
|
{ "%set/dar/obj/real",of_SET_DAR_OBJ_REAL,1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
2013-10-20 00:11:13 +02:00
|
|
|
{ "%set/dar/obj/str", of_SET_DAR_OBJ_STR, 1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
2014-02-07 20:24:41 +01:00
|
|
|
{ "%set/dar/obj/vec4",of_SET_DAR_OBJ_VEC4,1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%shiftl", of_SHIFTL, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%shiftr", of_SHIFTR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%shiftr/s", of_SHIFTR_S, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2014-02-07 00:05:26 +01:00
|
|
|
{ "%split/vec4", of_SPLIT_VEC4, 1,{OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%store/dar/r", of_STORE_DAR_R, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%store/dar/str", of_STORE_DAR_STR, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%store/dar/vec4",of_STORE_DAR_VEC4,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
2012-12-10 02:59:16 +01:00
|
|
|
{ "%store/obj", of_STORE_OBJ, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
2014-08-30 05:31:51 +02:00
|
|
|
{ "%store/obja", of_STORE_OBJA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
2014-10-21 20:46:59 +02:00
|
|
|
{ "%store/prop/obj",of_STORE_PROP_OBJ,2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
2013-01-14 02:14:40 +01:00
|
|
|
{ "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%store/prop/str",of_STORE_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
2014-10-21 20:46:59 +02:00
|
|
|
{ "%store/prop/v", of_STORE_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
2020-07-17 10:30:23 +02:00
|
|
|
{ "%store/qb/r", of_STORE_QB_R, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/qb/str", of_STORE_QB_STR, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/qb/v", of_STORE_QB_V, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
2020-08-07 09:21:28 +02:00
|
|
|
{ "%store/qdar/r", of_STORE_QDAR_R, 2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/qdar/str",of_STORE_QDAR_STR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/qdar/v", of_STORE_QDAR_V, 3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
2020-07-17 10:30:23 +02:00
|
|
|
{ "%store/qf/r", of_STORE_QF_R, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/qf/str", of_STORE_QF_STR, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/qf/v", of_STORE_QF_V, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
2020-08-07 09:21:28 +02:00
|
|
|
{ "%store/qobj/r", of_STORE_QOBJ_R, 2, {OA_FUNC_PTR,OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/qobj/str",of_STORE_QOBJ_STR,2, {OA_FUNC_PTR,OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/qobj/v", of_STORE_QOBJ_V, 3, {OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
2014-01-04 23:11:07 +01:00
|
|
|
{ "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%store/stra", of_STORE_STRA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
2014-01-05 19:30:59 +01:00
|
|
|
{ "%store/vec4", of_STORE_VEC4, 3, {OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
|
|
|
|
{ "%store/vec4a", of_STORE_VEC4A, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
2013-12-27 16:04:42 +01:00
|
|
|
{ "%sub", of_SUB, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2012-10-23 02:20:43 +02:00
|
|
|
{ "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-12-05 18:45:29 +01:00
|
|
|
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
2014-02-01 04:01:28 +01:00
|
|
|
{ "%substr", of_SUBSTR, 2,{OA_BIT1, OA_BIT2, OA_NONE} },
|
|
|
|
|
{ "%substr/vec4",of_SUBSTR_VEC4,2,{OA_BIT1, OA_BIT2, OA_NONE} },
|
2014-10-22 21:58:50 +02:00
|
|
|
{ "%test_nul", of_TEST_NUL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%test_nul/a", of_TEST_NUL_A, 2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
|
|
|
|
{ "%test_nul/obj", of_TEST_NUL_OBJ, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
|
|
|
|
{ "%test_nul/prop",of_TEST_NUL_PROP,2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
2001-03-26 06:00:39 +02:00
|
|
|
{ "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
2013-10-23 00:58:59 +02:00
|
|
|
{ "%wait/fork",of_WAIT_FORK,0,{OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-05 00:48:16 +01:00
|
|
|
{ "%xnor", of_XNOR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-05 23:12:27 +01:00
|
|
|
{ "%xnor/r", of_XNORR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-05 00:48:16 +01:00
|
|
|
{ "%xor", of_XOR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2014-01-05 23:12:27 +01:00
|
|
|
{ "%xor/r", of_XORR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
2001-03-11 01:29:38 +01:00
|
|
|
{ 0, of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }
|
|
|
|
|
};
|
|
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
static const unsigned opcode_count =
|
|
|
|
|
sizeof(opcode_table)/sizeof(*opcode_table) - 1;
|
2001-03-11 01:29:38 +01:00
|
|
|
|
|
|
|
|
static int opcode_compare(const void*k, const void*r)
|
|
|
|
|
{
|
|
|
|
|
const char*kp = (const char*)k;
|
|
|
|
|
const struct opcode_table_s*rp = (const struct opcode_table_s*)r;
|
|
|
|
|
return strcmp(kp, rp->mnemonic);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Keep a symbol table of addresses within code space. Labels on
|
|
|
|
|
* executable opcodes are mapped to their address here.
|
|
|
|
|
*/
|
|
|
|
|
static symbol_table_t sym_codespace = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Keep a symbol table of functors mentioned in the source. This table
|
|
|
|
|
* is used to resolve references as they come.
|
|
|
|
|
*/
|
|
|
|
|
static symbol_table_t sym_functors = 0;
|
|
|
|
|
|
2001-03-21 06:13:03 +01:00
|
|
|
/*
|
|
|
|
|
* VPI objects are indexed during compile time so that they can be
|
|
|
|
|
* linked together as they are created. This symbol table matches
|
|
|
|
|
* labels to vpiHandles.
|
|
|
|
|
*/
|
|
|
|
|
static symbol_table_t sym_vpi = 0;
|
|
|
|
|
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
/*
|
|
|
|
|
* If a functor parameter makes a forward reference to a functor, then
|
|
|
|
|
* I need to save that reference and resolve it after the functors are
|
|
|
|
|
* created. Use this structure to keep the unresolved references in an
|
|
|
|
|
* unsorted singly linked list.
|
2001-03-25 05:54:26 +02:00
|
|
|
*
|
|
|
|
|
* The postpone_functor_input arranges for a functor input to be
|
|
|
|
|
* resolved and connected at cleanup. This is used if the symbol is
|
|
|
|
|
* defined after its use in a functor. The ptr parameter is the
|
|
|
|
|
* complete vvp_input_t for the input port.
|
2001-03-11 01:29:38 +01:00
|
|
|
*/
|
2001-08-09 21:38:23 +02:00
|
|
|
|
|
|
|
|
|
2001-08-25 19:22:32 +02:00
|
|
|
/*
|
|
|
|
|
* Add a functor to the symbol table
|
|
|
|
|
*/
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
void define_functor_symbol(const char*label, vvp_net_t*net)
|
2001-08-25 19:22:32 +02:00
|
|
|
{
|
|
|
|
|
symbol_value_t val;
|
2004-12-11 03:31:25 +01:00
|
|
|
val.net = net;
|
2001-08-25 19:22:32 +02:00
|
|
|
sym_set_value(sym_functors, label, val);
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
static vvp_net_t*lookup_functor_symbol(const char*label)
|
2001-08-25 19:22:32 +02:00
|
|
|
{
|
2002-07-05 06:40:59 +02:00
|
|
|
assert(sym_functors);
|
2001-08-25 19:22:32 +02:00
|
|
|
symbol_value_t val = sym_get_value(sym_functors, label);
|
2004-12-11 03:31:25 +01:00
|
|
|
return val.net;
|
2001-08-25 19:22:32 +02:00
|
|
|
}
|
2001-10-12 04:53:47 +02:00
|
|
|
|
2008-03-20 21:07:18 +01:00
|
|
|
vpiHandle vvp_lookup_handle(const char*label)
|
|
|
|
|
{
|
|
|
|
|
symbol_value_t val = sym_get_value(sym_vpi, label);
|
|
|
|
|
if (val.ptr) return (vpiHandle) val.ptr;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-12 19:23:15 +02:00
|
|
|
vvp_net_t* vvp_net_lookup(const char*label)
|
2001-10-12 04:53:47 +02:00
|
|
|
{
|
2019-09-30 01:57:09 +02:00
|
|
|
static bool t0_trigger_generated = false;
|
|
|
|
|
|
2003-04-23 05:09:25 +02:00
|
|
|
/* First, look to see if the symbol is a vpi object of some
|
|
|
|
|
sort. If it is, then get the vvp_ipoint_t pointer out of
|
|
|
|
|
the vpiHandle. */
|
2001-10-12 04:53:47 +02:00
|
|
|
symbol_value_t val = sym_get_value(sym_vpi, label);
|
|
|
|
|
if (val.ptr) {
|
|
|
|
|
vpiHandle vpi = (vpiHandle) val.ptr;
|
2012-01-19 19:16:39 +01:00
|
|
|
switch (vpi->get_type_code()) {
|
2003-04-23 05:09:25 +02:00
|
|
|
case vpiNet:
|
|
|
|
|
case vpiReg:
|
2011-04-04 02:22:12 +02:00
|
|
|
case vpiBitVar:
|
2010-10-08 03:01:11 +02:00
|
|
|
case vpiByteVar:
|
|
|
|
|
case vpiShortIntVar:
|
|
|
|
|
case vpiIntVar:
|
|
|
|
|
case vpiLongIntVar:
|
2003-04-23 05:09:25 +02:00
|
|
|
case vpiIntegerVar: {
|
2012-01-23 05:37:01 +01:00
|
|
|
__vpiSignal*sig = dynamic_cast<__vpiSignal*>(vpi);
|
2004-12-11 03:31:25 +01:00
|
|
|
return sig->node;
|
2003-04-23 05:09:25 +02:00
|
|
|
}
|
|
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
case vpiRealVar: {
|
2012-01-23 05:37:01 +01:00
|
|
|
__vpiRealVar*sig = dynamic_cast<__vpiRealVar*>(vpi);
|
2005-07-06 06:29:25 +02:00
|
|
|
return sig->net;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-17 04:13:06 +01:00
|
|
|
case vpiStringVar:
|
|
|
|
|
case vpiArrayVar:
|
|
|
|
|
case vpiClassVar: {
|
|
|
|
|
__vpiBaseVar*sig = dynamic_cast<__vpiBaseVar*>(vpi);
|
2012-06-18 03:22:50 +02:00
|
|
|
return sig->get_net();
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-23 05:09:25 +02:00
|
|
|
case vpiNamedEvent: {
|
2012-01-23 05:37:01 +01:00
|
|
|
__vpiNamedEvent*tmp = dynamic_cast<__vpiNamedEvent*>(vpi);
|
2003-04-23 05:09:25 +02:00
|
|
|
return tmp->funct;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
2007-08-23 00:15:32 +02:00
|
|
|
fprintf(stderr, "Unsupported type %d.\n",
|
2012-01-19 19:16:39 +01:00
|
|
|
vpi->get_type_code());
|
2003-04-23 05:09:25 +02:00
|
|
|
assert(0);
|
|
|
|
|
}
|
2001-10-12 04:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2001-10-12 04:53:47 +02:00
|
|
|
/* Failing that, look for a general functor. */
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_net_t*tmp = lookup_functor_symbol(label);
|
2001-10-12 04:53:47 +02:00
|
|
|
|
2019-09-30 01:57:09 +02:00
|
|
|
// This is a special label used to create a T0 trigger for the
|
|
|
|
|
// always_comb/latch processes.
|
|
|
|
|
if (! t0_trigger_generated && (strcmp(label, "E_0x0") == 0)) {
|
|
|
|
|
// This should never happen, but if it does then the E_0x0
|
|
|
|
|
// event generation may need to be explicitly generated in
|
|
|
|
|
// the compiler output instead of implicitly in this code.
|
|
|
|
|
assert(! vpip_peek_current_scope()->is_automatic());
|
|
|
|
|
t0_trigger_generated = true;
|
|
|
|
|
// Create a local event with no name for the T0 trigger
|
|
|
|
|
compile_named_event(strdup(label), strcpy(new char [1],""), true);
|
|
|
|
|
tmp = vvp_net_lookup(label);
|
|
|
|
|
assert(tmp);
|
|
|
|
|
// Create a trigger for the T0 event.
|
|
|
|
|
vvp_net_ptr_t ptr (tmp, 0);
|
|
|
|
|
schedule_t0_trigger(ptr);
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-12 04:53:47 +02:00
|
|
|
return tmp;
|
|
|
|
|
}
|
2001-08-25 19:22:32 +02:00
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
/*
|
2001-08-10 06:31:09 +02:00
|
|
|
* The resolv_list_s is the base class for a symbol resolve action, and
|
|
|
|
|
* the resolv_list is an unordered list of these resolve actions. Some
|
|
|
|
|
* function creates an instance of a resolv_list_s object that
|
|
|
|
|
* contains the data pertinent to that resolution request, and
|
|
|
|
|
* executes it with the resolv_submit function. If the operation can
|
|
|
|
|
* complete, then the resolv_submit deletes the object. Otherwise, it
|
|
|
|
|
* pushes it onto the resolv_list for later processing.
|
|
|
|
|
*
|
|
|
|
|
* Derived classes implement the resolve function to perform the
|
|
|
|
|
* actual binding or resolution that the instance requires. If the
|
|
|
|
|
* function succeeds, the resolve method returns true and the object
|
|
|
|
|
* can be deleted any time.
|
|
|
|
|
*
|
|
|
|
|
* The mes parameter of the resolve method tells the resolver that
|
|
|
|
|
* this call is its last chance. If it cannot complete the operation,
|
|
|
|
|
* it must print an error message and return false.
|
2001-08-09 21:38:23 +02:00
|
|
|
*/
|
2012-02-12 22:21:30 +01:00
|
|
|
static resolv_list_s*resolv_list = 0;
|
2001-08-09 21:38:23 +02:00
|
|
|
|
2008-05-17 04:06:12 +02:00
|
|
|
resolv_list_s::~resolv_list_s()
|
|
|
|
|
{
|
|
|
|
|
free(label_);
|
|
|
|
|
}
|
2001-08-09 21:38:23 +02:00
|
|
|
|
2012-02-12 22:21:30 +01:00
|
|
|
void resolv_submit(resolv_list_s*cur)
|
2001-08-09 21:38:23 +02:00
|
|
|
{
|
2001-08-10 06:31:09 +02:00
|
|
|
if (cur->resolve()) {
|
|
|
|
|
delete cur;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-03-20 07:16:23 +01:00
|
|
|
|
2001-08-10 06:31:09 +02:00
|
|
|
cur->next = resolv_list;
|
|
|
|
|
resolv_list = cur;
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
|
|
|
|
|
2001-08-10 06:31:09 +02:00
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
/*
|
2004-12-11 03:31:25 +01:00
|
|
|
* Look up vvp_nets in the symbol table. The "source" is the label for
|
|
|
|
|
* the net that I want to feed, and net->port[port] is the vvp_net
|
|
|
|
|
* input that I want that node to feed into. When the name is found,
|
|
|
|
|
* put net->port[port] into the fan-out list for that node.
|
2001-08-09 21:38:23 +02:00
|
|
|
*/
|
2004-12-11 03:31:25 +01:00
|
|
|
struct vvp_net_resolv_list_s: public resolv_list_s {
|
2008-05-17 04:06:12 +02:00
|
|
|
|
2015-10-22 11:45:31 +02:00
|
|
|
explicit vvp_net_resolv_list_s(char*l) : resolv_list_s(l) { }
|
2004-12-11 03:31:25 +01:00
|
|
|
// port to be driven by the located node.
|
|
|
|
|
vvp_net_ptr_t port;
|
2001-08-09 21:38:23 +02:00
|
|
|
virtual bool resolve(bool mes);
|
2001-03-11 01:29:38 +01:00
|
|
|
};
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
bool vvp_net_resolv_list_s::resolve(bool mes)
|
2001-08-09 21:38:23 +02:00
|
|
|
{
|
2008-05-17 04:06:12 +02:00
|
|
|
vvp_net_t*tmp = vvp_net_lookup(label());
|
2001-08-25 19:22:32 +02:00
|
|
|
|
|
|
|
|
if (tmp) {
|
2004-12-11 03:31:25 +01:00
|
|
|
// Link the input port to the located output.
|
2009-04-04 05:40:26 +02:00
|
|
|
tmp->link(port);
|
2001-08-25 19:22:32 +02:00
|
|
|
return true;
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mes)
|
2008-05-17 04:06:12 +02:00
|
|
|
fprintf(stderr, "unresolved vvp_net reference: %s\n", label());
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2001-03-11 01:29:38 +01:00
|
|
|
|
2004-10-04 03:10:51 +02:00
|
|
|
inline static
|
2004-12-11 03:31:25 +01:00
|
|
|
void postpone_functor_input(vvp_net_ptr_t port, char*lab)
|
2001-03-25 05:54:26 +02:00
|
|
|
{
|
2008-05-17 04:06:12 +02:00
|
|
|
struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s(lab);
|
2004-12-11 03:31:25 +01:00
|
|
|
res->port = port;
|
2001-08-09 21:38:23 +02:00
|
|
|
|
2001-08-10 06:31:09 +02:00
|
|
|
resolv_submit(res);
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
/*
|
2001-10-09 18:57:47 +02:00
|
|
|
* Generic functor reference lookup.
|
2001-08-09 21:38:23 +02:00
|
|
|
*/
|
|
|
|
|
|
2001-10-09 18:57:47 +02:00
|
|
|
struct functor_gen_resolv_list_s: public resolv_list_s {
|
2011-04-30 02:55:01 +02:00
|
|
|
explicit functor_gen_resolv_list_s(char*txt) : resolv_list_s(txt) {
|
|
|
|
|
ref = 0;
|
|
|
|
|
}
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_net_t**ref;
|
2001-08-09 21:38:23 +02:00
|
|
|
virtual bool resolve(bool mes);
|
|
|
|
|
};
|
|
|
|
|
|
2001-10-09 18:57:47 +02:00
|
|
|
bool functor_gen_resolv_list_s::resolve(bool mes)
|
2001-08-09 21:38:23 +02:00
|
|
|
{
|
2008-05-17 04:06:12 +02:00
|
|
|
vvp_net_t*tmp = vvp_net_lookup(label());
|
2001-10-09 18:57:47 +02:00
|
|
|
|
2001-08-25 19:22:32 +02:00
|
|
|
if (tmp) {
|
2001-10-09 18:57:47 +02:00
|
|
|
*ref = tmp;
|
2001-08-25 19:22:32 +02:00
|
|
|
return true;
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
|
|
|
|
|
2001-10-09 18:57:47 +02:00
|
|
|
if (mes)
|
2008-05-17 04:06:12 +02:00
|
|
|
fprintf(stderr, "unresolved functor reference: %s\n", label());
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
void functor_ref_lookup(vvp_net_t**ref, char*lab)
|
2001-08-09 21:38:23 +02:00
|
|
|
{
|
2004-10-04 03:10:51 +02:00
|
|
|
struct functor_gen_resolv_list_s*res =
|
2008-05-17 04:06:12 +02:00
|
|
|
new struct functor_gen_resolv_list_s(lab);
|
2001-08-09 21:38:23 +02:00
|
|
|
|
2001-10-09 18:57:47 +02:00
|
|
|
res->ref = ref;
|
2001-08-09 21:38:23 +02:00
|
|
|
|
2001-08-10 06:31:09 +02:00
|
|
|
resolv_submit(res);
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* vpiHandle lookup
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
struct vpi_handle_resolv_list_s: public resolv_list_s {
|
2010-10-11 00:14:29 +02:00
|
|
|
explicit vpi_handle_resolv_list_s(char*lab) : resolv_list_s(lab) {
|
|
|
|
|
handle = NULL;
|
|
|
|
|
}
|
2001-08-09 21:38:23 +02:00
|
|
|
virtual bool resolve(bool mes);
|
2008-05-17 04:06:12 +02:00
|
|
|
vpiHandle *handle;
|
2001-08-09 21:38:23 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool vpi_handle_resolv_list_s::resolve(bool mes)
|
|
|
|
|
{
|
2008-05-17 04:06:12 +02:00
|
|
|
symbol_value_t val = sym_get_value(sym_vpi, label());
|
2001-08-09 21:38:23 +02:00
|
|
|
if (!val.ptr) {
|
2014-11-19 18:15:01 +01:00
|
|
|
// check for thread access symbols
|
2001-08-09 21:38:23 +02:00
|
|
|
unsigned base, wid;
|
2014-11-19 18:15:01 +01:00
|
|
|
size_t n = 0;
|
2002-04-14 04:56:19 +02:00
|
|
|
char ss[32];
|
2014-11-19 18:15:01 +01:00
|
|
|
if (2 == sscanf(label(), "W<%u,%[r]>%zn", &base, ss, &n)
|
2014-01-07 05:36:26 +01:00
|
|
|
&& n == strlen(label())) {
|
|
|
|
|
|
|
|
|
|
val.ptr = vpip_make_vthr_word(base, ss);
|
|
|
|
|
sym_set_value(sym_vpi, label(), val);
|
2002-04-14 04:56:19 +02:00
|
|
|
|
2014-11-19 18:15:01 +01:00
|
|
|
} else if (1 == sscanf(label(), "S<%u,str>%zn", &base, &n)
|
2012-06-25 00:33:40 +02:00
|
|
|
&& n == strlen(label())) {
|
|
|
|
|
|
|
|
|
|
val.ptr = vpip_make_vthr_str_stack(base);
|
|
|
|
|
sym_set_value(sym_vpi, label(), val);
|
2014-01-04 23:11:07 +01:00
|
|
|
|
2014-11-19 18:15:01 +01:00
|
|
|
} else if (3 == sscanf(label(), "S<%u,vec4,%[su]%u>%zn", &base, ss, &wid, &n)
|
2014-01-04 23:11:07 +01:00
|
|
|
&& n == strlen(label())) {
|
|
|
|
|
|
2014-01-07 05:27:14 +01:00
|
|
|
bool signed_flag = false;
|
|
|
|
|
for (char*fp = ss ; *fp ; fp += 1) switch (*fp) {
|
|
|
|
|
case 's':
|
|
|
|
|
signed_flag = true;
|
|
|
|
|
break;
|
|
|
|
|
case 'u':
|
|
|
|
|
signed_flag = false;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-01-15 02:10:03 +01:00
|
|
|
val.ptr = vpip_make_vthr_vec4_stack(base, signed_flag, wid);
|
2014-01-04 23:11:07 +01:00
|
|
|
sym_set_value(sym_vpi, label(), val);
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
2003-01-26 19:16:22 +01:00
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!val.ptr) {
|
|
|
|
|
// check for memory word M<mem,base,wid>
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 08:00:42 +01:00
|
|
|
if (strcmp(label(), "null") == 0) {
|
|
|
|
|
val.ptr = vpip_make_null_const();
|
|
|
|
|
sym_set_value(sym_vpi, label(), val);
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
if (val.ptr) {
|
|
|
|
|
*handle = (vpiHandle) val.ptr;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
if (mes)
|
2008-05-17 04:06:12 +02:00
|
|
|
fprintf(stderr, "unresolved vpi name lookup: %s\n", label());
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compile_vpi_lookup(vpiHandle *handle, char*label)
|
|
|
|
|
{
|
2002-12-21 01:55:57 +01:00
|
|
|
if (strcmp(label, "$time") == 0) {
|
2009-01-09 04:10:15 +01:00
|
|
|
*handle = vpip_sim_time(vpip_peek_current_scope(), false);
|
2002-12-21 01:55:57 +01:00
|
|
|
free(label);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strcmp(label, "$stime") == 0) {
|
2009-01-09 04:10:15 +01:00
|
|
|
*handle = vpip_sim_time(vpip_peek_current_scope(), true);
|
2002-12-21 01:55:57 +01:00
|
|
|
free(label);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-27 01:14:37 +01:00
|
|
|
if (strcmp(label, "$realtime") == 0) {
|
2003-02-01 06:50:04 +01:00
|
|
|
*handle = vpip_sim_realtime(vpip_peek_current_scope());
|
2003-01-27 01:14:37 +01:00
|
|
|
free(label);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-03 02:09:20 +01:00
|
|
|
if (strcmp(label, "$simtime") == 0) {
|
2009-01-09 04:10:15 +01:00
|
|
|
*handle = vpip_sim_time(0, false);
|
2003-02-03 02:09:20 +01:00
|
|
|
free(label);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-10 06:31:09 +02:00
|
|
|
struct vpi_handle_resolv_list_s*res
|
2008-05-17 04:06:12 +02:00
|
|
|
= new struct vpi_handle_resolv_list_s(label);
|
2001-08-09 21:38:23 +02:00
|
|
|
|
|
|
|
|
res->handle = handle;
|
2001-08-10 06:31:09 +02:00
|
|
|
resolv_submit(res);
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Code Label lookup
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
struct code_label_resolv_list_s: public resolv_list_s {
|
2015-12-27 22:07:42 +01:00
|
|
|
explicit code_label_resolv_list_s(char*lab, bool cptr2) : resolv_list_s(lab) {
|
2010-10-11 00:14:29 +02:00
|
|
|
code = NULL;
|
2015-12-27 22:07:42 +01:00
|
|
|
cptr2_flag = cptr2;
|
2010-10-11 00:14:29 +02:00
|
|
|
}
|
2001-08-09 21:38:23 +02:00
|
|
|
struct vvp_code_s *code;
|
2015-12-27 22:07:42 +01:00
|
|
|
bool cptr2_flag;
|
2001-08-09 21:38:23 +02:00
|
|
|
virtual bool resolve(bool mes);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool code_label_resolv_list_s::resolve(bool mes)
|
|
|
|
|
{
|
2008-05-17 04:06:12 +02:00
|
|
|
symbol_value_t val = sym_get_value(sym_codespace, label());
|
2019-08-01 13:34:47 +02:00
|
|
|
if (val.ptr) {
|
2015-12-27 22:07:42 +01:00
|
|
|
if (cptr2_flag)
|
2003-07-03 22:03:36 +02:00
|
|
|
code->cptr2 = reinterpret_cast<vvp_code_t>(val.ptr);
|
2001-08-09 21:38:23 +02:00
|
|
|
else
|
2003-07-03 22:03:36 +02:00
|
|
|
code->cptr = reinterpret_cast<vvp_code_t>(val.ptr);
|
2001-08-09 21:38:23 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mes)
|
2008-05-17 04:06:12 +02:00
|
|
|
fprintf(stderr, "unresolved code label: %s\n", label());
|
2001-08-09 21:38:23 +02:00
|
|
|
|
|
|
|
|
return false;
|
2001-03-25 05:54:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-27 22:07:42 +01:00
|
|
|
void code_label_lookup(struct vvp_code_s *code, char *label, bool cptr2)
|
2001-08-09 21:38:23 +02:00
|
|
|
{
|
2001-08-10 06:31:09 +02:00
|
|
|
struct code_label_resolv_list_s *res
|
2015-12-27 22:07:42 +01:00
|
|
|
= new struct code_label_resolv_list_s(label, cptr2);
|
2001-08-09 21:38:23 +02:00
|
|
|
|
|
|
|
|
res->code = code;
|
|
|
|
|
|
2001-08-10 06:31:09 +02:00
|
|
|
resolv_submit(res);
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
2001-03-25 05:54:26 +02:00
|
|
|
|
2008-05-17 04:06:12 +02:00
|
|
|
struct code_array_resolv_list_s: public resolv_list_s {
|
2015-10-22 11:45:31 +02:00
|
|
|
explicit code_array_resolv_list_s(char*lab) : resolv_list_s(lab) {
|
2010-10-11 00:14:29 +02:00
|
|
|
code = NULL;
|
|
|
|
|
}
|
2007-01-16 06:44:14 +01:00
|
|
|
struct vvp_code_s *code;
|
|
|
|
|
virtual bool resolve(bool mes);
|
|
|
|
|
};
|
|
|
|
|
|
2008-05-17 04:06:12 +02:00
|
|
|
bool code_array_resolv_list_s::resolve(bool mes)
|
2007-01-16 06:44:14 +01:00
|
|
|
{
|
2008-05-17 04:06:12 +02:00
|
|
|
code->array = array_find(label());
|
2007-01-16 06:44:14 +01:00
|
|
|
if (code->array != 0) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mes)
|
2008-05-17 04:06:12 +02:00
|
|
|
fprintf(stderr, "Array unresolved: %s\n", label());
|
2007-01-16 06:44:14 +01:00
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void compile_array_lookup(struct vvp_code_s*code, char*label)
|
|
|
|
|
{
|
2008-05-17 04:06:12 +02:00
|
|
|
struct code_array_resolv_list_s *res
|
|
|
|
|
= new struct code_array_resolv_list_s(label);
|
2007-01-16 06:44:14 +01:00
|
|
|
|
|
|
|
|
res->code = code;
|
|
|
|
|
|
|
|
|
|
resolv_submit(res);
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-04 21:43:33 +02:00
|
|
|
static std::list<struct __vpiSysTaskCall*> scheduled_compiletf;
|
2007-07-25 03:24:24 +02:00
|
|
|
|
|
|
|
|
void compile_compiletf(struct __vpiSysTaskCall*obj)
|
|
|
|
|
{
|
|
|
|
|
if (obj->defn->info.compiletf == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
scheduled_compiletf.push_back(obj);
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
/*
|
|
|
|
|
* When parsing is otherwise complete, this function is called to do
|
|
|
|
|
* the final stuff. Clean up deferred linking here.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void compile_cleanup(void)
|
|
|
|
|
{
|
|
|
|
|
int lnerrs = -1;
|
|
|
|
|
int nerrs = 0;
|
|
|
|
|
int last;
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2002-07-15 02:21:42 +02:00
|
|
|
if (verbose_flag) {
|
|
|
|
|
fprintf(stderr, " ... Linking\n");
|
|
|
|
|
fflush(stderr);
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-09 21:38:23 +02:00
|
|
|
do {
|
2012-02-12 22:21:30 +01:00
|
|
|
resolv_list_s *res = resolv_list;
|
2001-08-09 21:38:23 +02:00
|
|
|
resolv_list = 0x0;
|
|
|
|
|
last = nerrs == lnerrs;
|
|
|
|
|
lnerrs = nerrs;
|
|
|
|
|
nerrs = 0;
|
|
|
|
|
while (res) {
|
2012-02-12 22:21:30 +01:00
|
|
|
resolv_list_s *cur = res;
|
2001-08-09 21:38:23 +02:00
|
|
|
res = res->next;
|
|
|
|
|
if (cur->resolve(last))
|
|
|
|
|
delete cur;
|
|
|
|
|
else {
|
|
|
|
|
nerrs++;
|
|
|
|
|
cur->next = resolv_list;
|
|
|
|
|
resolv_list = cur;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-10-09 18:57:47 +02:00
|
|
|
if (nerrs && last)
|
2004-10-04 03:10:51 +02:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"compile_cleanup: %d unresolved items\n",
|
2001-08-09 21:38:23 +02:00
|
|
|
nerrs);
|
2001-10-09 18:57:47 +02:00
|
|
|
} while (nerrs && !last);
|
2001-08-09 21:38:23 +02:00
|
|
|
|
|
|
|
|
compile_errors += nerrs;
|
2002-07-05 04:50:57 +02:00
|
|
|
|
2002-07-15 02:21:42 +02:00
|
|
|
if (verbose_flag) {
|
|
|
|
|
fprintf(stderr, " ... Removing symbol tables\n");
|
|
|
|
|
fflush(stderr);
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-05 06:40:59 +02:00
|
|
|
/* After compile is complete, the vpi symbol table is no
|
|
|
|
|
longer needed. VPI objects are located by following
|
|
|
|
|
scopes. */
|
2002-07-05 04:50:57 +02:00
|
|
|
delete_symbol_table(sym_vpi);
|
|
|
|
|
sym_vpi = 0;
|
2002-07-05 06:40:59 +02:00
|
|
|
|
|
|
|
|
/* Don't need the code labels. The instructions have numeric
|
|
|
|
|
pointers in them, the symbol table is no longer needed. */
|
|
|
|
|
delete_symbol_table(sym_codespace);
|
|
|
|
|
sym_codespace = 0;
|
|
|
|
|
|
|
|
|
|
delete_symbol_table(sym_functors);
|
|
|
|
|
sym_functors = 0;
|
2007-07-25 03:24:24 +02:00
|
|
|
|
2009-01-30 02:23:09 +01:00
|
|
|
delete_udp_symbols();
|
|
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
compile_island_cleanup();
|
2009-01-22 01:16:49 +01:00
|
|
|
compile_array_cleanup();
|
2008-06-01 06:45:55 +02:00
|
|
|
|
2007-07-25 03:24:24 +02:00
|
|
|
if (verbose_flag) {
|
|
|
|
|
fprintf(stderr, " ... Compiletf functions\n");
|
|
|
|
|
fflush(stderr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(vpi_mode_flag == VPI_MODE_NONE);
|
|
|
|
|
vpi_mode_flag = VPI_MODE_COMPILETF;
|
|
|
|
|
|
|
|
|
|
while (! scheduled_compiletf.empty()) {
|
|
|
|
|
struct __vpiSysTaskCall*obj = scheduled_compiletf.front();
|
|
|
|
|
scheduled_compiletf.pop_front();
|
|
|
|
|
vpip_cur_task = obj;
|
|
|
|
|
obj->defn->info.compiletf (obj->defn->info.user_data);
|
|
|
|
|
vpip_cur_task = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vpi_mode_flag = VPI_MODE_NONE;
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
2001-03-11 01:29:38 +01:00
|
|
|
|
2001-03-31 21:00:43 +02:00
|
|
|
void compile_vpi_symbol(const char*label, vpiHandle obj)
|
|
|
|
|
{
|
|
|
|
|
symbol_value_t val;
|
|
|
|
|
val.ptr = obj;
|
|
|
|
|
sym_set_value(sym_vpi, label, val);
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
/*
|
|
|
|
|
* Initialize the compiler by allocation empty symbol tables and
|
|
|
|
|
* initializing the various address spaces.
|
|
|
|
|
*/
|
|
|
|
|
void compile_init(void)
|
|
|
|
|
{
|
2001-03-21 06:13:03 +01:00
|
|
|
sym_vpi = new_symbol_table();
|
2001-03-31 21:00:43 +02:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
sym_functors = new_symbol_table();
|
2001-03-31 21:00:43 +02:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
sym_codespace = new_symbol_table();
|
|
|
|
|
codespace_init();
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-23 03:40:22 +01:00
|
|
|
void compile_load_vpi_module(char*name)
|
|
|
|
|
{
|
2001-07-26 05:13:51 +02:00
|
|
|
vpip_load_module(name);
|
2009-01-13 18:57:12 +01:00
|
|
|
delete[] name;
|
2001-03-23 03:40:22 +01:00
|
|
|
}
|
|
|
|
|
|
2001-07-01 01:03:16 +02:00
|
|
|
void compile_vpi_time_precision(long pre)
|
|
|
|
|
{
|
|
|
|
|
vpip_set_time_precision(pre);
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-22 03:16:19 +01:00
|
|
|
/*
|
|
|
|
|
* Convert a Cr string value to double.
|
2008-09-04 18:41:51 +02:00
|
|
|
*
|
2008-03-22 03:16:19 +01:00
|
|
|
* The format is broken into mantissa and exponent.
|
|
|
|
|
* The exponent in turn includes a sign bit.
|
|
|
|
|
*
|
|
|
|
|
* The mantissa is a 64bit integer value (encoded in hex).
|
|
|
|
|
*
|
|
|
|
|
* The exponent included the sign bit (0x4000) and the binary
|
|
|
|
|
* exponent offset by 0x1000. The actual exponent is the
|
|
|
|
|
* encoded exponent - 0x1000.
|
|
|
|
|
*
|
|
|
|
|
* The real value is sign * (mant ** exp).
|
|
|
|
|
*/
|
2009-08-24 06:37:16 +02:00
|
|
|
bool crstring_test(const char*str)
|
2008-03-22 03:16:19 +01:00
|
|
|
{
|
2009-08-24 06:37:16 +02:00
|
|
|
if (strncmp(str, "Cr<", 3) != 0) return false;
|
|
|
|
|
const char*tp = strchr(str, '>');
|
|
|
|
|
if (tp == 0) return false;
|
|
|
|
|
if (tp[1] != 0) return false;
|
|
|
|
|
|
2009-09-24 20:29:46 +02:00
|
|
|
if ((strspn(str+3, "0123456789abcdefmg")+3) != (size_t)(tp - str))
|
2009-08-24 06:37:16 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double crstring_to_double(const char*label)
|
|
|
|
|
{
|
|
|
|
|
const char*cp = label+3;
|
2008-03-22 03:16:19 +01:00
|
|
|
assert(*cp == 'm');
|
|
|
|
|
cp += 1;
|
2009-08-24 06:37:16 +02:00
|
|
|
char*ep;
|
|
|
|
|
uint64_t mant = strtoull(cp, &ep, 16);
|
|
|
|
|
cp = ep;
|
2008-03-22 03:16:19 +01:00
|
|
|
assert(*cp == 'g');
|
|
|
|
|
cp += 1;
|
|
|
|
|
int exp = strtoul(cp, 0, 16);
|
|
|
|
|
|
|
|
|
|
double tmp;
|
|
|
|
|
if (mant == 0 && exp == 0x3fff) {
|
|
|
|
|
tmp = INFINITY;
|
|
|
|
|
} else if (mant == 0 && exp == 0x7fff) {
|
|
|
|
|
tmp = -INFINITY;
|
|
|
|
|
} else if (exp == 0x3fff) {
|
|
|
|
|
tmp = nan("");
|
|
|
|
|
} else {
|
|
|
|
|
double sign = (exp & 0x4000)? -1.0 : 1.0;
|
|
|
|
|
exp &= 0x1fff;
|
|
|
|
|
|
|
|
|
|
tmp = sign * ldexp((double)mant, exp - 0x1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2004-10-04 03:10:51 +02:00
|
|
|
/*
|
2004-12-11 03:31:25 +01:00
|
|
|
* Run through the arguments looking for the nodes that are
|
2001-04-28 22:24:03 +02:00
|
|
|
* connected to my input ports. For each source functor that I
|
|
|
|
|
* find, connect the output of that functor to the indexed
|
|
|
|
|
* input by inserting myself (complete with the port number in
|
|
|
|
|
* the vvp_ipoint_t) into the list that the source heads.
|
2004-10-04 03:10:51 +02:00
|
|
|
*
|
2001-04-28 22:24:03 +02:00
|
|
|
* If the source functor is not declared yet, then don't do
|
2001-04-30 05:53:19 +02:00
|
|
|
* the link yet. Save the reference to be resolved later.
|
|
|
|
|
*
|
|
|
|
|
* If the source is a constant value, then set the ival of the functor
|
|
|
|
|
* and skip the symbol lookup.
|
|
|
|
|
*/
|
2001-04-28 22:24:03 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
void input_connect(vvp_net_t*fdx, unsigned port, char*label)
|
2001-04-28 22:24:03 +02:00
|
|
|
{
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_net_ptr_t ifdx = vvp_net_ptr_t(fdx, port);
|
|
|
|
|
|
|
|
|
|
/* Is this a vvp_vector4_t constant value? */
|
2009-08-24 06:37:16 +02:00
|
|
|
if (c4string_test(label)) {
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2006-03-08 06:29:42 +01:00
|
|
|
vvp_vector4_t tmp = c4string_to_vector4(label);
|
2001-04-28 22:24:03 +02:00
|
|
|
|
2005-01-29 18:53:25 +01:00
|
|
|
// Inputs that are constants are schedule to execute as
|
|
|
|
|
// soon at the simulation starts. In Verilog, constants
|
|
|
|
|
// start propagating when the simulation starts, just
|
|
|
|
|
// like any other signal value. But letting the
|
|
|
|
|
// scheduler distribute the constant value has the
|
|
|
|
|
// additional advantage that the constant is not
|
|
|
|
|
// propagated until the network is fully linked.
|
|
|
|
|
schedule_set_vector(ifdx, tmp);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
free(label);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-07-28 05:12:39 +02:00
|
|
|
|
2005-02-12 04:27:18 +01:00
|
|
|
/* Is this a vvp_vector8_t constant value? */
|
2009-08-29 17:53:44 +02:00
|
|
|
if (c8string_test(label)) {
|
2005-02-12 04:27:18 +01:00
|
|
|
|
2009-08-29 17:53:44 +02:00
|
|
|
vvp_vector8_t tmp = c8string_to_vector8(label);
|
2005-02-12 04:27:18 +01:00
|
|
|
schedule_set_vector(ifdx, tmp);
|
|
|
|
|
|
|
|
|
|
free(label);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-20 01:27:09 +01:00
|
|
|
/* Handle the Cr<> constant driver, which is a real-value
|
2008-03-22 03:16:19 +01:00
|
|
|
driver. */
|
2009-08-24 06:37:16 +02:00
|
|
|
if (crstring_test(label)) {
|
2005-07-06 06:29:25 +02:00
|
|
|
|
2008-03-22 03:16:19 +01:00
|
|
|
double tmp = crstring_to_double(label);
|
2005-07-06 06:29:25 +02:00
|
|
|
|
|
|
|
|
schedule_set_vector(ifdx, tmp);
|
|
|
|
|
free(label);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/* Handle the general case that this is a label for a node in
|
|
|
|
|
the vvp net. This arranges for the label to be preserved in
|
|
|
|
|
a linker list, and linked when the symbol table is
|
|
|
|
|
complete. */
|
|
|
|
|
postpone_functor_input(ifdx, label);
|
|
|
|
|
}
|
2001-05-09 04:53:25 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
2005-05-25 07:44:51 +02:00
|
|
|
if (argc > 4) {
|
2012-06-04 21:43:33 +02:00
|
|
|
std::cerr << "XXXX argv[0] = " << argv[0].text << std::endl;
|
2005-05-25 07:44:51 +02:00
|
|
|
}
|
2004-12-11 03:31:25 +01:00
|
|
|
assert(argc <= 4);
|
2001-10-31 05:27:46 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
for (unsigned idx = 0; idx < argc; idx += 1) {
|
2001-05-09 04:53:25 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
input_connect(fdx, idx, argv[idx].text);
|
2001-04-30 05:53:19 +02:00
|
|
|
}
|
2001-04-28 22:24:03 +02:00
|
|
|
}
|
|
|
|
|
|
2005-04-01 08:02:45 +02:00
|
|
|
void wide_inputs_connect(vvp_wide_fun_core*core,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
/* Create input functors to receive values from the
|
|
|
|
|
network. These functors pass the data to the core. */
|
|
|
|
|
unsigned input_functors = (argc+3) / 4;
|
|
|
|
|
for (unsigned idx = 0 ; idx < input_functors ; idx += 1) {
|
|
|
|
|
unsigned base = idx*4;
|
|
|
|
|
unsigned trans = 4;
|
|
|
|
|
if (base+trans > argc)
|
|
|
|
|
trans = argc - base;
|
|
|
|
|
|
|
|
|
|
vvp_wide_fun_t*cur = new vvp_wide_fun_t(core, base);
|
|
|
|
|
vvp_net_t*ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = cur;
|
|
|
|
|
|
|
|
|
|
inputs_connect(ptr, trans, argv+base);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
template <class T_> void make_arith(T_ *arith, char*label,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
2001-06-07 05:09:03 +02:00
|
|
|
{
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_net_t* ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = arith;
|
2001-10-31 05:27:46 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
define_functor_symbol(label, ptr);
|
2001-10-31 05:27:46 +01:00
|
|
|
free(label);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
assert(argc == 2);
|
|
|
|
|
inputs_connect(ptr, argc, argv);
|
2001-06-07 05:09:03 +02:00
|
|
|
|
|
|
|
|
free(argv);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-21 03:11:11 +02:00
|
|
|
void compile_arith_cast_int(char*label, long width,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
2008-06-18 02:07:19 +02:00
|
|
|
{
|
2008-06-21 03:11:11 +02:00
|
|
|
vvp_arith_cast_int*arith = new vvp_arith_cast_int((unsigned) width);
|
|
|
|
|
|
|
|
|
|
vvp_net_t* ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = arith;
|
|
|
|
|
|
|
|
|
|
define_functor_symbol(label, ptr);
|
|
|
|
|
free(label);
|
|
|
|
|
|
|
|
|
|
assert(argc == 1);
|
|
|
|
|
inputs_connect(ptr, argc, argv);
|
|
|
|
|
free(argv);
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 19:53:20 +02:00
|
|
|
void compile_arith_cast_vec2(char*label, long width,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
vvp_arith_cast_vec2*arith = new vvp_arith_cast_vec2((unsigned) width);
|
|
|
|
|
|
|
|
|
|
vvp_net_t* ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = arith;
|
|
|
|
|
|
|
|
|
|
define_functor_symbol(label, ptr);
|
|
|
|
|
free(label);
|
|
|
|
|
|
|
|
|
|
assert(argc == 1);
|
|
|
|
|
inputs_connect(ptr, argc, argv);
|
|
|
|
|
free(argv);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-21 03:11:11 +02:00
|
|
|
void compile_arith_cast_real(char*label, bool signed_flag,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
vvp_arith_cast_real*arith = new vvp_arith_cast_real(signed_flag);
|
2008-06-18 02:07:19 +02:00
|
|
|
|
|
|
|
|
vvp_net_t* ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = arith;
|
|
|
|
|
|
|
|
|
|
define_functor_symbol(label, ptr);
|
|
|
|
|
free(label);
|
|
|
|
|
|
|
|
|
|
assert(argc == 1);
|
|
|
|
|
inputs_connect(ptr, argc, argv);
|
|
|
|
|
free(argv);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-07 05:37:00 +02:00
|
|
|
void compile_arith_abs(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
vvp_arith_abs*arith = new vvp_arith_abs;
|
|
|
|
|
|
|
|
|
|
vvp_net_t* ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = arith;
|
|
|
|
|
|
|
|
|
|
define_functor_symbol(label, ptr);
|
|
|
|
|
free(label);
|
|
|
|
|
|
|
|
|
|
assert(argc == 1);
|
|
|
|
|
inputs_connect(ptr, argc, argv);
|
|
|
|
|
free(argv);
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-30 04:15:57 +02:00
|
|
|
void compile_arith_div(char*label, long wid, bool signed_flag,
|
2001-10-16 04:47:37 +02:00
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2005-02-19 02:32:52 +01:00
|
|
|
if (argc != 2) {
|
2008-02-15 00:25:43 +01:00
|
|
|
const char *suffix = "";
|
2008-02-09 02:32:57 +01:00
|
|
|
if (signed_flag) suffix = ".s";
|
|
|
|
|
fprintf(stderr, "%s; .arith/div%s has wrong number of "
|
|
|
|
|
"symbols\n", label, suffix);
|
2001-10-16 04:47:37 +02:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-30 04:15:57 +02:00
|
|
|
vvp_arith_ *arith = new vvp_arith_div(wid, signed_flag);
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s; .arith/divr has wrong number of symbols\n", label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_arith_div_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
2001-10-16 04:47:37 +02:00
|
|
|
}
|
|
|
|
|
|
2008-11-08 03:23:04 +01:00
|
|
|
void compile_arith_mod(char*label, long wid, bool signed_flag,
|
2002-01-03 05:19:01 +01:00
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2005-03-12 07:42:28 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .arith/mod has wrong number of symbols\n", label);
|
2002-01-03 05:19:01 +01:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-08 03:23:04 +01:00
|
|
|
vvp_arith_ *arith = new vvp_arith_mod(wid, signed_flag);
|
2002-01-03 05:19:01 +01:00
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2008-01-31 03:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compile_arith_mod_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .arith/mod.r has wrong number of symbols\n", label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_arith_mod_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
2002-01-03 05:19:01 +01:00
|
|
|
}
|
|
|
|
|
|
2001-06-17 01:45:05 +02:00
|
|
|
void compile_arith_mult(char*label, long wid,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2005-01-28 06:34:25 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .arith/mult has wrong number of symbols\n", label);
|
2001-06-17 01:45:05 +02:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-31 05:27:46 +01:00
|
|
|
vvp_arith_ *arith = new vvp_arith_mult(wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2001-06-17 01:45:05 +02:00
|
|
|
}
|
|
|
|
|
|
2008-01-04 08:44:14 +01:00
|
|
|
void compile_arith_mult_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .arith/mult.r has wrong number of symbols\n", label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_arith_mult_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-06 04:09:30 +01:00
|
|
|
|
2008-02-09 02:32:57 +01:00
|
|
|
void compile_arith_pow(char*label, long wid, bool signed_flag,
|
2008-02-06 04:09:30 +01:00
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
|
|
|
|
if (argc != 2) {
|
2008-02-15 00:25:43 +01:00
|
|
|
const char *suffix = "";
|
2008-02-09 02:32:57 +01:00
|
|
|
if (signed_flag) suffix = ".s";
|
|
|
|
|
fprintf(stderr, "%s .arith/pow%s has wrong number of "
|
|
|
|
|
"symbols\n", label, suffix);
|
2008-02-06 04:09:30 +01:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-09 02:32:57 +01:00
|
|
|
vvp_arith_ *arith = new vvp_arith_pow(wid, signed_flag);
|
2008-02-06 04:09:30 +01:00
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-31 02:53:06 +01:00
|
|
|
void compile_arith_pow_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .arith/pow.r has wrong number of symbols\n", label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_arith_pow_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-07 05:09:03 +02:00
|
|
|
void compile_arith_sub(char*label, long wid, unsigned argc, struct symb_s*argv)
|
2001-06-05 05:05:41 +02:00
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2005-01-30 06:06:49 +01:00
|
|
|
if (argc != 2) {
|
2008-01-04 08:44:14 +01:00
|
|
|
fprintf(stderr, "%s .arith/sub has wrong number of symbols\n", label);
|
2001-06-05 05:05:41 +02:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-31 05:27:46 +01:00
|
|
|
vvp_arith_ *arith = new vvp_arith_sub(wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compile_arith_sub_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s; .arith/sub.r has wrong number of symbols\n", label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_arith_sub_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
2001-06-07 05:09:03 +02:00
|
|
|
}
|
2001-06-05 05:05:41 +02:00
|
|
|
|
2001-06-07 05:09:03 +02:00
|
|
|
void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
2001-06-05 05:05:41 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
if (argc != 2) {
|
2008-01-04 08:44:14 +01:00
|
|
|
fprintf(stderr, "%s .arith/sum has wrong number of symbols\n", label);
|
2001-06-07 05:09:03 +02:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
2001-06-05 05:05:41 +02:00
|
|
|
}
|
|
|
|
|
|
2001-10-31 05:27:46 +01:00
|
|
|
vvp_arith_ *arith = new vvp_arith_sum(wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2001-06-05 05:05:41 +02:00
|
|
|
}
|
|
|
|
|
|
2008-01-04 08:44:14 +01:00
|
|
|
void compile_arith_sum_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .arith/sum.r has wrong number of symbols\n", label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_arith_sum_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-22 02:06:20 +01:00
|
|
|
void compile_cmp_eeq(char*label, long wid,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/eeq has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_ *arith = new vvp_cmp_eeq(wid);
|
|
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2005-01-22 02:06:20 +01:00
|
|
|
}
|
|
|
|
|
|
2005-03-09 06:52:03 +01:00
|
|
|
void compile_cmp_nee(char*label, long wid,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/eeq has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_ *arith = new vvp_cmp_nee(wid);
|
|
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2005-03-09 06:52:03 +01:00
|
|
|
}
|
|
|
|
|
|
2004-06-16 18:33:25 +02:00
|
|
|
void compile_cmp_eq(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2005-01-22 17:21:11 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/eq has wrong number of symbols\n",label);
|
2004-06-16 18:33:25 +02:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_ *arith = new vvp_cmp_eq(wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2004-06-16 18:33:25 +02:00
|
|
|
}
|
|
|
|
|
|
2014-06-14 03:01:41 +02:00
|
|
|
void compile_cmp_eqx(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/eqx has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_ *arith = new vvp_cmp_eqx(wid);
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compile_cmp_eqz(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/eqz has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_ *arith = new vvp_cmp_eqz(wid);
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-15 19:54:04 +01:00
|
|
|
void compile_cmp_eq_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/eq.r has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_cmp_eq_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-16 18:33:25 +02:00
|
|
|
void compile_cmp_ne(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2005-01-22 17:21:11 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/ne has wrong number of symbols\n",label);
|
2004-06-16 18:33:25 +02:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_ *arith = new vvp_cmp_ne(wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2004-06-16 18:33:25 +02:00
|
|
|
}
|
|
|
|
|
|
2008-01-15 19:54:04 +01:00
|
|
|
void compile_cmp_ne_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/ne.r has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_cmp_ne_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-11 07:15:38 +02:00
|
|
|
void compile_cmp_ge(char*label, long wid, bool signed_flag,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
2001-06-15 06:07:57 +02:00
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2005-01-16 05:19:08 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/ge has wrong number of symbols\n", label);
|
2001-06-15 06:07:57 +02:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-11 07:15:38 +02:00
|
|
|
vvp_arith_ *arith = new vvp_cmp_ge(wid, signed_flag);
|
2001-06-15 06:07:57 +02:00
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2001-06-15 06:07:57 +02:00
|
|
|
}
|
|
|
|
|
|
2008-01-15 19:54:04 +01:00
|
|
|
void compile_cmp_ge_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/ge.r has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_cmp_ge_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-11 07:15:38 +02:00
|
|
|
void compile_cmp_gt(char*label, long wid, bool signed_flag,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
2001-06-15 06:07:57 +02:00
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2005-05-18 05:46:01 +02:00
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/gt has wrong number of symbols\n", label);
|
2001-06-15 06:07:57 +02:00
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-11 07:15:38 +02:00
|
|
|
vvp_arith_ *arith = new vvp_cmp_gt(wid, signed_flag);
|
2001-06-15 06:07:57 +02:00
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2001-06-15 06:07:57 +02:00
|
|
|
}
|
|
|
|
|
|
2008-01-15 19:54:04 +01:00
|
|
|
void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/gt.r has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_real_ *arith = new vvp_cmp_gt_real;
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-18 04:32:09 +01:00
|
|
|
void compile_cmp_weq(char*label, long wid,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/weq has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_ *arith = new vvp_cmp_weq(wid);
|
|
|
|
|
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compile_cmp_wne(char*label, long wid,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
|
|
|
|
if (argc != 2) {
|
|
|
|
|
fprintf(stderr, "%s .cmp/wne has wrong number of symbols\n",label);
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_arith_ *arith = new vvp_cmp_wne(wid);
|
|
|
|
|
|
|
|
|
|
make_arith(arith, label, argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-02 06:32:06 +01:00
|
|
|
|
2010-04-08 12:48:17 +02:00
|
|
|
void compile_delay(char*label, unsigned width,
|
|
|
|
|
vvp_delay_t*delay, struct symb_s arg)
|
2006-01-02 06:32:06 +01:00
|
|
|
{
|
|
|
|
|
vvp_net_t*net = new vvp_net_t;
|
2010-04-08 12:48:17 +02:00
|
|
|
vvp_fun_delay*obj = new vvp_fun_delay(net, width, *delay);
|
2006-01-02 06:32:06 +01:00
|
|
|
net->fun = obj;
|
|
|
|
|
|
|
|
|
|
delete delay;
|
|
|
|
|
|
|
|
|
|
input_connect(net, 0, arg.text);
|
|
|
|
|
|
|
|
|
|
define_functor_symbol(label, net);
|
|
|
|
|
free(label);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-08 12:48:17 +02:00
|
|
|
void compile_delay(char*label, unsigned width,
|
2010-07-13 19:01:32 +02:00
|
|
|
unsigned argc, struct symb_s*argv, bool ignore_decay)
|
2006-01-02 06:32:06 +01:00
|
|
|
{
|
|
|
|
|
vvp_delay_t stub (0, 0, 0);
|
2010-07-13 19:01:32 +02:00
|
|
|
if (ignore_decay) stub.set_ignore_decay();
|
2006-01-02 06:32:06 +01:00
|
|
|
vvp_net_t*net = new vvp_net_t;
|
2010-04-08 12:48:17 +02:00
|
|
|
vvp_fun_delay*obj = new vvp_fun_delay(net, width, stub);
|
2006-01-02 06:32:06 +01:00
|
|
|
net->fun = obj;
|
|
|
|
|
|
|
|
|
|
inputs_connect(net, argc, argv);
|
|
|
|
|
free(argv);
|
|
|
|
|
|
|
|
|
|
define_functor_symbol(label, net);
|
|
|
|
|
free(label);
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-24 03:43:27 +02:00
|
|
|
/*
|
|
|
|
|
* Extend nodes.
|
|
|
|
|
*/
|
|
|
|
|
void compile_extend_signed(char*label, long wid, struct symb_s arg)
|
|
|
|
|
{
|
|
|
|
|
assert(wid >= 0);
|
|
|
|
|
|
|
|
|
|
vvp_fun_extend_signed*fun = new vvp_fun_extend_signed(wid);
|
|
|
|
|
vvp_net_t*ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = fun;
|
|
|
|
|
|
|
|
|
|
define_functor_symbol(label, ptr);
|
|
|
|
|
free(label);
|
|
|
|
|
|
|
|
|
|
input_connect(ptr, 0, arg.text);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-08 12:48:17 +02:00
|
|
|
struct __vpiModPath* compile_modpath(char*label, unsigned width,
|
|
|
|
|
struct symb_s drv, struct symb_s dest)
|
2006-09-23 06:57:19 +02:00
|
|
|
{
|
|
|
|
|
vvp_net_t*net = new vvp_net_t;
|
2010-04-08 12:48:17 +02:00
|
|
|
vvp_fun_modpath*obj = new vvp_fun_modpath(net, width);
|
2006-09-23 06:57:19 +02:00
|
|
|
net->fun = obj;
|
|
|
|
|
|
2007-11-03 03:59:08 +01:00
|
|
|
input_connect(net, 0, drv.text);
|
2006-09-23 06:57:19 +02:00
|
|
|
|
|
|
|
|
define_functor_symbol(label, net);
|
2007-10-31 04:14:40 +01:00
|
|
|
|
2007-11-06 04:58:20 +01:00
|
|
|
__vpiModPath*modpath = vpip_make_modpath(net);
|
2007-10-31 04:14:40 +01:00
|
|
|
|
2007-11-03 03:59:08 +01:00
|
|
|
compile_vpi_lookup(&modpath->path_term_out.expr, dest.text);
|
|
|
|
|
|
2007-11-06 04:58:20 +01:00
|
|
|
free(label);
|
|
|
|
|
|
2007-10-31 04:14:40 +01:00
|
|
|
modpath->modpath = obj;
|
|
|
|
|
return modpath;
|
2006-09-23 06:57:19 +02:00
|
|
|
}
|
|
|
|
|
|
2007-11-06 04:58:20 +01:00
|
|
|
static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path,
|
|
|
|
|
char edge,
|
2016-08-15 07:25:38 +02:00
|
|
|
const struct symb_s&src,
|
|
|
|
|
struct numbv_s&vals,
|
2008-04-29 04:00:29 +02:00
|
|
|
bool ifnone)
|
2006-09-23 06:57:19 +02:00
|
|
|
{
|
2007-10-31 04:14:40 +01:00
|
|
|
vvp_fun_modpath*dst = path->modpath;
|
2006-09-23 06:57:19 +02:00
|
|
|
|
2007-10-31 04:14:40 +01:00
|
|
|
vvp_time64_t use_delay[12];
|
2006-09-23 06:57:19 +02:00
|
|
|
assert(vals.cnt == 12);
|
2006-09-29 05:57:01 +02:00
|
|
|
for (unsigned idx = 0 ; idx < vals.cnt ; idx += 1) {
|
|
|
|
|
use_delay[idx] = vals.nvec[idx];
|
2006-09-23 06:57:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
numbv_clear(&vals);
|
|
|
|
|
|
2007-03-02 07:13:22 +01:00
|
|
|
vvp_fun_modpath_src*obj = 0;
|
|
|
|
|
|
2007-12-14 05:42:06 +01:00
|
|
|
int vpi_edge = vpiNoEdge;
|
2007-03-02 07:13:22 +01:00
|
|
|
if (edge == 0) {
|
|
|
|
|
obj = new vvp_fun_modpath_src(use_delay);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
bool posedge, negedge;
|
|
|
|
|
switch (edge) {
|
|
|
|
|
case '+':
|
2007-12-14 05:42:06 +01:00
|
|
|
vpi_edge = vpiPosedge;
|
2007-03-02 07:13:22 +01:00
|
|
|
posedge = true;
|
|
|
|
|
negedge = false;
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2007-12-14 05:42:06 +01:00
|
|
|
vpi_edge = vpiNegedge;
|
2007-03-02 07:13:22 +01:00
|
|
|
posedge = false;
|
|
|
|
|
negedge = true;
|
|
|
|
|
break;
|
2007-12-14 05:42:06 +01:00
|
|
|
#if 0
|
2007-03-02 07:13:22 +01:00
|
|
|
case '*':
|
|
|
|
|
posedge = true;
|
2007-12-14 05:42:06 +01:00
|
|
|
negedge = true;
|
2007-03-02 07:13:22 +01:00
|
|
|
break;
|
2007-12-14 05:42:06 +01:00
|
|
|
#endif
|
2007-03-02 07:13:22 +01:00
|
|
|
default:
|
2009-12-10 21:53:58 +01:00
|
|
|
posedge = false;
|
|
|
|
|
negedge = false;
|
2007-08-23 00:15:32 +02:00
|
|
|
fprintf(stderr, "Unknown edge identifier %c(%d).\n", edge,
|
|
|
|
|
edge);
|
2007-03-02 07:13:22 +01:00
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
obj = new vvp_fun_modpath_edge(use_delay, posedge, negedge);
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-23 06:57:19 +02:00
|
|
|
vvp_net_t*net = new vvp_net_t;
|
2010-10-11 06:52:26 +02:00
|
|
|
struct __vpiModPathSrc* srcobj = vpip_make_modpath_src(path, net) ;
|
2012-01-19 19:16:39 +01:00
|
|
|
vpip_attach_to_current_scope(srcobj);
|
2007-09-11 00:30:00 +02:00
|
|
|
net->fun = obj;
|
2007-12-14 05:42:06 +01:00
|
|
|
|
|
|
|
|
/* Save the vpiEdge directory into the input path term. */
|
|
|
|
|
srcobj->path_term_in.edge = vpi_edge;
|
2006-09-23 06:57:19 +02:00
|
|
|
input_connect(net, 0, src.text);
|
2008-04-29 04:00:29 +02:00
|
|
|
dst->add_modpath_src(obj, ifnone);
|
2008-09-04 18:41:51 +02:00
|
|
|
|
2007-11-06 04:58:20 +01:00
|
|
|
return srcobj;
|
2007-03-01 07:19:38 +01:00
|
|
|
}
|
|
|
|
|
|
2007-10-31 04:14:40 +01:00
|
|
|
void compile_modpath_src(struct __vpiModPath*dst, char edge,
|
2016-08-15 07:25:38 +02:00
|
|
|
const struct symb_s&src,
|
|
|
|
|
struct numbv_s&vals,
|
|
|
|
|
const struct symb_s&condit_src,
|
|
|
|
|
const struct symb_s&path_term_in)
|
2007-03-01 07:19:38 +01:00
|
|
|
{
|
2008-04-29 04:00:29 +02:00
|
|
|
struct __vpiModPathSrc*obj =
|
|
|
|
|
make_modpath_src(dst, edge, src, vals, false);
|
2007-11-06 04:58:20 +01:00
|
|
|
input_connect(obj->net, 1, condit_src.text);
|
|
|
|
|
compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text);
|
2007-03-01 07:19:38 +01:00
|
|
|
}
|
|
|
|
|
|
2007-10-31 04:14:40 +01:00
|
|
|
void compile_modpath_src(struct __vpiModPath*dst, char edge,
|
2016-08-15 07:25:38 +02:00
|
|
|
const struct symb_s&src,
|
|
|
|
|
struct numbv_s&vals,
|
2007-11-06 04:58:20 +01:00
|
|
|
int condit_src,
|
2016-08-15 07:25:38 +02:00
|
|
|
const struct symb_s&path_term_in,
|
2008-04-29 04:00:29 +02:00
|
|
|
bool ifnone)
|
2007-03-01 07:19:38 +01:00
|
|
|
{
|
2007-11-06 04:58:20 +01:00
|
|
|
assert(condit_src == 0);
|
2008-04-29 04:00:29 +02:00
|
|
|
struct __vpiModPathSrc*obj =
|
|
|
|
|
make_modpath_src(dst, edge, src, vals, ifnone);
|
2007-11-06 04:58:20 +01:00
|
|
|
compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text);
|
2006-09-23 06:57:19 +02:00
|
|
|
}
|
|
|
|
|
|
2001-07-06 07:02:43 +02:00
|
|
|
/*
|
|
|
|
|
* A .shift/l statement creates an array of functors for the
|
|
|
|
|
* width. The 0 input is the data vector to be shifted and the 1 input
|
|
|
|
|
* is the amount of the shift. An unconnected shift amount is set to 0.
|
|
|
|
|
*/
|
2001-07-06 06:46:44 +02:00
|
|
|
void compile_shiftl(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
|
|
|
|
|
2001-10-31 05:27:46 +01:00
|
|
|
vvp_arith_ *arith = new vvp_shiftl(wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2001-07-07 04:57:33 +02:00
|
|
|
}
|
2001-07-06 07:02:43 +02:00
|
|
|
|
2006-07-30 04:51:35 +02:00
|
|
|
void compile_shiftr(char*label, long wid, bool signed_flag,
|
|
|
|
|
unsigned argc, struct symb_s*argv)
|
2001-07-07 04:57:33 +02:00
|
|
|
{
|
|
|
|
|
assert( wid > 0 );
|
2001-07-06 06:46:44 +02:00
|
|
|
|
2006-07-30 04:51:35 +02:00
|
|
|
vvp_arith_ *arith = new vvp_shiftr(wid, signed_flag);
|
2005-07-06 06:29:25 +02:00
|
|
|
make_arith(arith, label, argc, argv);
|
2001-07-06 06:46:44 +02:00
|
|
|
}
|
|
|
|
|
|
2001-05-09 04:53:25 +02:00
|
|
|
void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
2012-07-10 22:15:34 +02:00
|
|
|
vvp_net_t*net = new vvp_net_t;
|
2001-05-09 04:53:25 +02:00
|
|
|
|
2012-07-10 22:15:34 +02:00
|
|
|
resolv_core*core = 0;
|
2001-12-15 02:54:38 +01:00
|
|
|
|
2012-07-10 22:15:34 +02:00
|
|
|
if (strcmp(type,"tri") == 0) {
|
|
|
|
|
core = new resolv_tri(argc, net, vvp_scalar_t(BIT4_Z, 0,0));
|
2007-07-12 06:38:56 +02:00
|
|
|
|
2001-12-15 02:54:38 +01:00
|
|
|
} else if (strcmp(type,"tri0") == 0) {
|
2012-07-10 22:15:34 +02:00
|
|
|
core = new resolv_tri(argc, net, vvp_scalar_t(BIT4_0, 5,5));
|
2001-12-15 02:54:38 +01:00
|
|
|
|
|
|
|
|
} else if (strcmp(type,"tri1") == 0) {
|
2012-07-10 22:15:34 +02:00
|
|
|
core = new resolv_tri(argc, net, vvp_scalar_t(BIT4_1, 5,5));
|
2001-05-12 22:38:06 +02:00
|
|
|
|
2003-07-30 03:13:28 +02:00
|
|
|
} else if (strcmp(type,"triand") == 0) {
|
2012-07-10 22:15:34 +02:00
|
|
|
core = new resolv_triand(argc, net);
|
2003-07-30 03:13:28 +02:00
|
|
|
|
|
|
|
|
} else if (strcmp(type,"trior") == 0) {
|
2012-07-10 22:15:34 +02:00
|
|
|
core = new resolv_trior(argc, net);
|
2003-07-30 03:13:28 +02:00
|
|
|
|
2001-05-12 22:38:06 +02:00
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, "invalid resolver type: %s\n", type);
|
|
|
|
|
compile_errors += 1;
|
2012-09-01 03:22:11 +02:00
|
|
|
delete net;
|
2001-05-12 22:38:06 +02:00
|
|
|
}
|
2001-05-09 04:53:25 +02:00
|
|
|
|
2012-07-10 22:15:34 +02:00
|
|
|
if (core) {
|
|
|
|
|
net->fun = core;
|
2004-12-11 03:31:25 +01:00
|
|
|
define_functor_symbol(label, net);
|
2012-07-10 22:15:34 +02:00
|
|
|
|
|
|
|
|
for (unsigned base = 0 ; base < argc ; base += 4) {
|
|
|
|
|
unsigned nports = argc - base;
|
|
|
|
|
if (nports > 4)
|
|
|
|
|
nports = 4;
|
|
|
|
|
|
|
|
|
|
if (base > 0) {
|
|
|
|
|
net = new vvp_net_t;
|
|
|
|
|
net->fun = new resolv_extend(core, base);
|
|
|
|
|
}
|
|
|
|
|
inputs_connect(net, nports, argv+base);
|
|
|
|
|
}
|
2001-10-31 05:27:46 +01:00
|
|
|
}
|
2001-05-09 04:53:25 +02:00
|
|
|
free(type);
|
2001-10-31 05:27:46 +01:00
|
|
|
free(label);
|
|
|
|
|
free(argv);
|
2001-05-09 04:53:25 +02:00
|
|
|
}
|
|
|
|
|
|
2001-04-24 04:23:58 +02:00
|
|
|
void compile_udp_def(int sequ, char *label, char *name,
|
|
|
|
|
unsigned nin, unsigned init, char **table)
|
|
|
|
|
{
|
2005-06-09 06:12:30 +02:00
|
|
|
if (sequ) {
|
2005-06-09 07:04:45 +02:00
|
|
|
vvp_bit4_t init4;
|
|
|
|
|
if (init == 0)
|
|
|
|
|
init4 = BIT4_0;
|
|
|
|
|
else if (init == 1)
|
|
|
|
|
init4 = BIT4_1;
|
|
|
|
|
else
|
|
|
|
|
init4 = BIT4_X;
|
|
|
|
|
|
|
|
|
|
vvp_udp_seq_s *u = new vvp_udp_seq_s(label, name, nin, init4);
|
2005-06-09 06:12:30 +02:00
|
|
|
u->compile_table(table);
|
|
|
|
|
} else {
|
|
|
|
|
vvp_udp_comb_s *u = new vvp_udp_comb_s(label, name, nin);
|
|
|
|
|
u->compile_table(table);
|
|
|
|
|
}
|
2005-04-01 08:02:45 +02:00
|
|
|
free(label);
|
2001-04-24 04:23:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char **compile_udp_table(char **table, char *row)
|
|
|
|
|
{
|
|
|
|
|
if (table)
|
|
|
|
|
assert(strlen(*table)==strlen(row));
|
|
|
|
|
|
|
|
|
|
char **tt;
|
2010-10-11 06:52:26 +02:00
|
|
|
for (tt = table; tt && *tt; tt++) { }
|
2001-04-24 04:23:58 +02:00
|
|
|
int n = (tt-table) + 2;
|
|
|
|
|
|
|
|
|
|
table = (char**)realloc(table, n*sizeof(char*));
|
|
|
|
|
table[n-2] = row;
|
|
|
|
|
table[n-1] = 0x0;
|
|
|
|
|
|
|
|
|
|
return table;
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-01 03:09:39 +02:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
/*
|
2001-10-31 05:27:46 +01:00
|
|
|
* The parser uses this function to compile and link an executable
|
2001-03-11 01:29:38 +01:00
|
|
|
* opcode. I do this by looking up the opcode in the opcode_table. The
|
2003-02-10 00:33:26 +01:00
|
|
|
* table gives the operand structure that is acceptable, so I can
|
2001-03-11 01:29:38 +01:00
|
|
|
* process the operands here as well.
|
|
|
|
|
*/
|
|
|
|
|
void compile_code(char*label, char*mnem, comp_operands_t opa)
|
|
|
|
|
{
|
|
|
|
|
/* First, I can give the label a value that is the current
|
|
|
|
|
codespace pointer. Don't need the text of the label after
|
|
|
|
|
this is done. */
|
2004-10-04 03:10:51 +02:00
|
|
|
if (label)
|
2001-08-09 21:38:23 +02:00
|
|
|
compile_codelabel(label);
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
/* Lookup the opcode in the opcode table. */
|
|
|
|
|
struct opcode_table_s*op = (struct opcode_table_s*)
|
|
|
|
|
bsearch(mnem, opcode_table, opcode_count,
|
|
|
|
|
sizeof(struct opcode_table_s), &opcode_compare);
|
|
|
|
|
if (op == 0) {
|
|
|
|
|
yyerror("Invalid opcode");
|
2004-12-15 18:17:42 +01:00
|
|
|
compile_errors += 1;
|
2001-03-11 01:29:38 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(op);
|
|
|
|
|
|
|
|
|
|
/* Build up the code from the information about the opcode and
|
2001-08-08 03:05:06 +02:00
|
|
|
the information from the compiler. */
|
2003-07-03 22:03:36 +02:00
|
|
|
vvp_code_t code = codespace_allocate();
|
2001-03-11 01:29:38 +01:00
|
|
|
code->opcode = op->opcode;
|
|
|
|
|
|
|
|
|
|
if (op->argc != (opa? opa->argc : 0)) {
|
|
|
|
|
yyerror("operand count");
|
2004-12-15 18:17:42 +01:00
|
|
|
compile_errors += 1;
|
2001-03-11 01:29:38 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Pull the operands that the instruction expects from the
|
|
|
|
|
list that the parser supplied. */
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < op->argc ; idx += 1) {
|
2001-03-18 01:37:55 +01:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
switch (op->argt[idx]) {
|
|
|
|
|
case OA_NONE:
|
|
|
|
|
break;
|
|
|
|
|
|
2008-09-04 18:41:51 +02:00
|
|
|
case OA_ARR_PTR:
|
2007-01-16 06:44:14 +01:00
|
|
|
if (opa->argv[idx].ltype != L_SYMB) {
|
|
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compile_array_lookup(code, opa->argv[idx].symb.text);
|
|
|
|
|
break;
|
|
|
|
|
|
2001-03-12 00:06:49 +01:00
|
|
|
case OA_BIT1:
|
2001-03-11 01:29:38 +01:00
|
|
|
if (opa->argv[idx].ltype != L_NUMB) {
|
|
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-11-01 04:00:19 +01:00
|
|
|
code->bit_idx[0] = opa->argv[idx].numb;
|
2001-03-12 00:06:49 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OA_BIT2:
|
|
|
|
|
if (opa->argv[idx].ltype != L_NUMB) {
|
|
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-11-01 04:00:19 +01:00
|
|
|
code->bit_idx[1] = opa->argv[idx].numb;
|
2001-03-11 01:29:38 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OA_CODE_PTR:
|
2015-12-27 22:07:42 +01:00
|
|
|
case OA_CODE_PTR2:
|
2001-03-20 07:16:23 +01:00
|
|
|
if (opa->argv[idx].ltype != L_SYMB) {
|
2001-03-11 01:29:38 +01:00
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
assert(opa->argv[idx].symb.idx == 0);
|
2015-12-27 22:07:42 +01:00
|
|
|
code_label_lookup(code, opa->argv[idx].symb.text,
|
|
|
|
|
op->argt[idx]==OA_CODE_PTR2);
|
2001-03-11 01:29:38 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OA_FUNC_PTR:
|
2001-06-10 19:12:51 +02:00
|
|
|
/* The operand is a functor. Resolve the label to
|
|
|
|
|
a functor pointer, or postpone the resolution
|
|
|
|
|
if it is not defined yet. */
|
2001-03-20 07:16:23 +01:00
|
|
|
if (opa->argv[idx].ltype != L_SYMB) {
|
2001-03-11 01:29:38 +01:00
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
functor_ref_lookup(&code->net, opa->argv[idx].symb.text);
|
2001-03-11 01:29:38 +01:00
|
|
|
break;
|
|
|
|
|
|
2001-11-01 04:00:19 +01:00
|
|
|
case OA_FUNC_PTR2:
|
|
|
|
|
/* The operand is a functor. Resolve the label to
|
|
|
|
|
a functor pointer, or postpone the resolution
|
|
|
|
|
if it is not defined yet. */
|
|
|
|
|
if (opa->argv[idx].ltype != L_SYMB) {
|
|
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
functor_ref_lookup(&code->net2, opa->argv[idx].symb.text);
|
2001-11-01 04:00:19 +01:00
|
|
|
break;
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
case OA_NUMBER:
|
|
|
|
|
if (opa->argv[idx].ltype != L_NUMB) {
|
|
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
code->number = opa->argv[idx].numb;
|
|
|
|
|
break;
|
|
|
|
|
|
2002-08-28 19:15:06 +02:00
|
|
|
case OA_VPI_PTR:
|
|
|
|
|
/* The operand is a functor. Resolve the label to
|
|
|
|
|
a functor pointer, or postpone the resolution
|
|
|
|
|
if it is not defined yet. */
|
|
|
|
|
if (opa->argv[idx].ltype != L_SYMB) {
|
|
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compile_vpi_lookup(&code->handle, opa->argv[idx].symb.text);
|
|
|
|
|
break;
|
2012-06-18 03:43:25 +02:00
|
|
|
|
|
|
|
|
case OA_STRING:
|
|
|
|
|
if (opa->argv[idx].ltype != L_STRING) {
|
|
|
|
|
yyerror("operand format");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
code->text = opa->argv[idx].text;
|
|
|
|
|
break;
|
2001-03-11 01:29:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-14 06:29:15 +02:00
|
|
|
free(opa);
|
2001-03-11 01:29:38 +01:00
|
|
|
|
|
|
|
|
free(mnem);
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-01 08:40:44 +02:00
|
|
|
void compile_codelabel(char*label)
|
|
|
|
|
{
|
|
|
|
|
symbol_value_t val;
|
2003-07-03 22:03:36 +02:00
|
|
|
vvp_code_t ptr = codespace_next();
|
2001-04-01 08:40:44 +02:00
|
|
|
|
2003-07-03 22:03:36 +02:00
|
|
|
val.ptr = ptr;
|
2001-04-01 08:40:44 +02:00
|
|
|
sym_set_value(sym_codespace, label, val);
|
|
|
|
|
|
|
|
|
|
free(label);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-28 04:20:16 +01:00
|
|
|
void compile_file_line(char*label, long file_idx, long lineno,
|
|
|
|
|
char*description)
|
|
|
|
|
{
|
|
|
|
|
if (label) compile_codelabel(label);
|
|
|
|
|
|
|
|
|
|
/* Create an instruction in the code space. */
|
|
|
|
|
vvp_code_t code = codespace_allocate();
|
|
|
|
|
code->opcode = &of_FILE_LINE;
|
|
|
|
|
|
|
|
|
|
/* Create a vpiHandle that contains the information. */
|
|
|
|
|
code->handle = vpip_build_file_line(description, file_idx, lineno);
|
|
|
|
|
assert(code->handle);
|
|
|
|
|
|
|
|
|
|
/* Done with the lexor-allocated name string. */
|
|
|
|
|
delete[] description;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-01 18:45:02 +01:00
|
|
|
void compile_vpi_call(char*label, char*name,
|
2010-06-09 20:56:00 +02:00
|
|
|
bool func_as_task_err, bool func_as_task_warn,
|
2008-04-30 03:58:25 +02:00
|
|
|
long file_idx, long lineno,
|
2012-10-23 02:20:43 +02:00
|
|
|
unsigned argc, vpiHandle*argv,
|
2014-01-04 23:06:58 +01:00
|
|
|
unsigned vec4_stack, unsigned real_stack, unsigned string_stack)
|
2001-03-16 02:44:34 +01:00
|
|
|
{
|
2001-08-09 21:38:23 +02:00
|
|
|
if (label)
|
|
|
|
|
compile_codelabel(label);
|
2001-03-16 02:44:34 +01:00
|
|
|
|
|
|
|
|
/* Create an instruction in the code space. */
|
2003-07-03 22:03:36 +02:00
|
|
|
vvp_code_t code = codespace_allocate();
|
2001-03-16 02:44:34 +01:00
|
|
|
code->opcode = &of_VPI_CALL;
|
|
|
|
|
|
|
|
|
|
/* Create a vpiHandle that bundles the call information, and
|
|
|
|
|
store that handle in the instruction. */
|
2014-01-04 23:06:58 +01:00
|
|
|
code->handle = vpip_build_vpi_call(name, 0, 0,
|
|
|
|
|
0, func_as_task_err, func_as_task_warn,
|
|
|
|
|
argc, argv, vec4_stack, real_stack, string_stack,
|
2012-10-23 02:20:43 +02:00
|
|
|
file_idx, lineno);
|
2001-05-20 02:46:12 +02:00
|
|
|
if (code->handle == 0)
|
|
|
|
|
compile_errors += 1;
|
|
|
|
|
|
|
|
|
|
/* Done with the lexor-allocated name string. */
|
2009-01-13 18:57:12 +01:00
|
|
|
delete[] name;
|
2001-05-20 02:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compile_vpi_func_call(char*label, char*name,
|
2014-01-04 23:06:58 +01:00
|
|
|
int val_type, unsigned val_wid,
|
2008-04-30 03:58:25 +02:00
|
|
|
long file_idx, long lineno,
|
2012-10-23 02:20:43 +02:00
|
|
|
unsigned argc, vpiHandle*argv,
|
2014-01-04 23:06:58 +01:00
|
|
|
unsigned vec4_stack,
|
2012-10-23 02:20:43 +02:00
|
|
|
unsigned real_stack,
|
|
|
|
|
unsigned string_stack)
|
2001-05-20 02:46:12 +02:00
|
|
|
{
|
2004-10-04 03:10:51 +02:00
|
|
|
if (label)
|
2001-08-09 21:38:23 +02:00
|
|
|
compile_codelabel(label);
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2001-05-20 02:46:12 +02:00
|
|
|
/* Create an instruction in the code space. */
|
2003-07-03 22:03:36 +02:00
|
|
|
vvp_code_t code = codespace_allocate();
|
2001-05-20 02:46:12 +02:00
|
|
|
code->opcode = &of_VPI_CALL;
|
|
|
|
|
|
|
|
|
|
/* Create a vpiHandle that bundles the call information, and
|
|
|
|
|
store that handle in the instruction. */
|
2014-01-04 23:06:58 +01:00
|
|
|
code->handle = vpip_build_vpi_call(name, val_type, val_wid,
|
|
|
|
|
0, true, false,
|
|
|
|
|
argc, argv, vec4_stack, real_stack, string_stack,
|
2012-10-23 02:20:43 +02:00
|
|
|
file_idx, lineno);
|
2001-03-22 23:38:13 +01:00
|
|
|
if (code->handle == 0)
|
|
|
|
|
compile_errors += 1;
|
2001-03-16 02:44:34 +01:00
|
|
|
|
|
|
|
|
/* Done with the lexor-allocated name string. */
|
2009-01-13 18:57:12 +01:00
|
|
|
delete[] name;
|
2001-03-16 02:44:34 +01:00
|
|
|
}
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
/*
|
|
|
|
|
* When the parser finds a thread statement, I create a new thread
|
|
|
|
|
* with the start address referenced by the program symbol passed to
|
|
|
|
|
* me.
|
|
|
|
|
*/
|
2003-09-04 22:26:30 +02:00
|
|
|
void compile_thread(char*start_sym, char*flag)
|
2001-03-11 01:29:38 +01:00
|
|
|
{
|
2003-09-04 22:26:30 +02:00
|
|
|
bool push_flag = false;
|
|
|
|
|
|
2001-03-18 01:37:55 +01:00
|
|
|
symbol_value_t tmp = sym_get_value(sym_codespace, start_sym);
|
2003-07-03 22:03:36 +02:00
|
|
|
vvp_code_t pc = reinterpret_cast<vvp_code_t>(tmp.ptr);
|
2001-03-11 01:29:38 +01:00
|
|
|
if (pc == 0) {
|
|
|
|
|
yyerror("unresolved address");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-04 22:26:30 +02:00
|
|
|
if (flag && (strcmp(flag,"$push") == 0))
|
|
|
|
|
push_flag = true;
|
|
|
|
|
|
2001-04-18 06:21:23 +02:00
|
|
|
vthread_t thr = vthread_new(pc, vpip_peek_current_scope());
|
2011-03-30 08:42:26 +02:00
|
|
|
|
2016-03-19 14:46:09 +01:00
|
|
|
if (flag && (strcmp(flag,"$init") == 0))
|
|
|
|
|
schedule_init_vthread(thr);
|
|
|
|
|
else if (flag && (strcmp(flag,"$final") == 0))
|
2011-03-30 08:42:26 +02:00
|
|
|
schedule_final_vthread(thr);
|
|
|
|
|
else
|
|
|
|
|
schedule_vthread(thr, 0, push_flag);
|
2003-09-04 22:26:30 +02:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
free(start_sym);
|
2010-04-14 06:29:15 +02:00
|
|
|
free(flag);
|
2001-03-11 01:29:38 +01:00
|
|
|
}
|
|
|
|
|
|
2008-05-06 04:46:30 +02:00
|
|
|
void compile_param_logic(char*label, char*name, char*value, bool signed_flag,
|
2012-06-04 21:43:33 +02:00
|
|
|
bool local_flag,
|
2008-05-06 04:46:30 +02:00
|
|
|
long file_idx, long lineno)
|
2003-03-11 00:37:07 +01:00
|
|
|
{
|
2006-03-08 06:29:42 +01:00
|
|
|
vvp_vector4_t value4 = c4string_to_vector4(value);
|
2008-05-06 04:46:30 +02:00
|
|
|
vpiHandle obj = vpip_make_binary_param(name, value4, signed_flag,
|
2012-06-04 21:43:33 +02:00
|
|
|
local_flag, file_idx, lineno);
|
2006-03-08 06:29:42 +01:00
|
|
|
compile_vpi_symbol(label, obj);
|
|
|
|
|
vpip_attach_to_current_scope(obj);
|
|
|
|
|
|
|
|
|
|
free(label);
|
|
|
|
|
free(value);
|
|
|
|
|
}
|
2003-03-11 00:37:07 +01:00
|
|
|
|
2008-05-06 04:46:30 +02:00
|
|
|
void compile_param_string(char*label, char*name, char*value,
|
2012-06-04 21:43:33 +02:00
|
|
|
bool local_flag,
|
2008-05-06 04:46:30 +02:00
|
|
|
long file_idx, long lineno)
|
2006-03-08 06:29:42 +01:00
|
|
|
{
|
2015-06-02 19:40:24 +02:00
|
|
|
// name and value become owned by vpip_make_string_param
|
2012-06-04 21:43:33 +02:00
|
|
|
vpiHandle obj = vpip_make_string_param(name, value, local_flag, file_idx, lineno);
|
2003-03-11 00:37:07 +01:00
|
|
|
compile_vpi_symbol(label, obj);
|
|
|
|
|
vpip_attach_to_current_scope(obj);
|
|
|
|
|
|
|
|
|
|
free(label);
|
|
|
|
|
}
|
2008-03-22 03:16:19 +01:00
|
|
|
|
2008-05-06 04:46:30 +02:00
|
|
|
void compile_param_real(char*label, char*name, char*value,
|
2012-06-04 21:43:33 +02:00
|
|
|
bool local_flag,
|
2008-05-06 04:46:30 +02:00
|
|
|
long file_idx, long lineno)
|
2008-03-22 03:16:19 +01:00
|
|
|
{
|
|
|
|
|
double dvalue = crstring_to_double(value);
|
2012-06-04 21:43:33 +02:00
|
|
|
vpiHandle obj = vpip_make_real_param(name, dvalue, local_flag, file_idx, lineno);
|
2008-03-22 03:16:19 +01:00
|
|
|
compile_vpi_symbol(label, obj);
|
|
|
|
|
vpip_attach_to_current_scope(obj);
|
|
|
|
|
|
|
|
|
|
free(label);
|
|
|
|
|
free(value);
|
|
|
|
|
}
|
2008-11-29 19:05:31 +01:00
|
|
|
|
|
|
|
|
void compile_island(char*label, char*type)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(type,"tran") == 0)
|
|
|
|
|
compile_island_tran(label);
|
|
|
|
|
else
|
|
|
|
|
assert(0);
|
|
|
|
|
|
|
|
|
|
free(type);
|
|
|
|
|
}
|