Normalize the parsing of %fork and %disable opcodes.
This commit is contained in:
parent
f275dac7a8
commit
1b33bf8615
|
|
@ -595,7 +595,7 @@ void compile_class_property(unsigned idx, char*nam, char*typ, uint64_t array_siz
|
|||
|
||||
void compile_class_done(void)
|
||||
{
|
||||
struct __vpiScope*scope = vpip_peek_current_scope();
|
||||
__vpiScope*scope = vpip_peek_current_scope();
|
||||
assert(scope);
|
||||
assert(compile_class);
|
||||
compile_class->finish_setup();
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ enum operand_e {
|
|||
OA_BIT2,
|
||||
/* The operand is a pointer to code space */
|
||||
OA_CODE_PTR,
|
||||
OA_CODE_PTR2,
|
||||
/* The operand is a variable or net pointer */
|
||||
OA_FUNC_PTR,
|
||||
/* The operand is a second functor pointer */
|
||||
|
|
@ -141,6 +142,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%delete/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||
{ "%disable", of_DISABLE, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
|
||||
{ "%disable/fork",of_DISABLE_FORK,0,{OA_NONE,OA_NONE, OA_NONE} },
|
||||
{ "%div", of_DIV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%div/s", of_DIV_S, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
|
|
@ -163,6 +165,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%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} },
|
||||
{ "%force/wr", of_FORCE_WR, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%fork", of_FORK, 2, {OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} },
|
||||
{ "%free", of_FREE, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%inv", of_INV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%ix/add", of_IX_ADD, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
||||
|
|
@ -627,10 +630,12 @@ void compile_vpi_lookup(vpiHandle *handle, char*label)
|
|||
*/
|
||||
|
||||
struct code_label_resolv_list_s: public resolv_list_s {
|
||||
explicit code_label_resolv_list_s(char*lab) : resolv_list_s(lab) {
|
||||
explicit code_label_resolv_list_s(char*lab, bool cptr2) : resolv_list_s(lab) {
|
||||
code = NULL;
|
||||
cptr2_flag = cptr2;
|
||||
}
|
||||
struct vvp_code_s *code;
|
||||
bool cptr2_flag;
|
||||
virtual bool resolve(bool mes);
|
||||
};
|
||||
|
||||
|
|
@ -638,7 +643,7 @@ bool code_label_resolv_list_s::resolve(bool mes)
|
|||
{
|
||||
symbol_value_t val = sym_get_value(sym_codespace, label());
|
||||
if (val.num) {
|
||||
if (code->opcode == of_FORK)
|
||||
if (cptr2_flag)
|
||||
code->cptr2 = reinterpret_cast<vvp_code_t>(val.ptr);
|
||||
else
|
||||
code->cptr = reinterpret_cast<vvp_code_t>(val.ptr);
|
||||
|
|
@ -651,10 +656,10 @@ bool code_label_resolv_list_s::resolve(bool mes)
|
|||
return false;
|
||||
}
|
||||
|
||||
void code_label_lookup(struct vvp_code_s *code, char *label)
|
||||
void code_label_lookup(struct vvp_code_s *code, char *label, bool cptr2)
|
||||
{
|
||||
struct code_label_resolv_list_s *res
|
||||
= new struct code_label_resolv_list_s(label);
|
||||
= new struct code_label_resolv_list_s(label, cptr2);
|
||||
|
||||
res->code = code;
|
||||
|
||||
|
|
@ -1724,13 +1729,15 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
|
|||
break;
|
||||
|
||||
case OA_CODE_PTR:
|
||||
case OA_CODE_PTR2:
|
||||
if (opa->argv[idx].ltype != L_SYMB) {
|
||||
yyerror("operand format");
|
||||
break;
|
||||
}
|
||||
|
||||
assert(opa->argv[idx].symb.idx == 0);
|
||||
code_label_lookup(code, opa->argv[idx].symb.text);
|
||||
code_label_lookup(code, opa->argv[idx].symb.text,
|
||||
op->argt[idx]==OA_CODE_PTR2);
|
||||
break;
|
||||
|
||||
case OA_FUNC_PTR:
|
||||
|
|
@ -1805,42 +1812,6 @@ void compile_codelabel(char*label)
|
|||
free(label);
|
||||
}
|
||||
|
||||
|
||||
void compile_disable(char*label, struct symb_s symb)
|
||||
{
|
||||
if (label)
|
||||
compile_codelabel(label);
|
||||
|
||||
/* Fill in the basics of the %disable in the instruction. */
|
||||
vvp_code_t code = codespace_allocate();
|
||||
code->opcode = of_DISABLE;
|
||||
|
||||
compile_vpi_lookup(&code->handle, symb.text);
|
||||
}
|
||||
|
||||
/*
|
||||
* The %fork instruction is a little different from other instructions
|
||||
* in that it has an extended field that holds the information needed
|
||||
* to create the new thread. This includes the target PC and scope.
|
||||
* I get these from the parser in the form of symbols.
|
||||
*/
|
||||
void compile_fork(char*label, struct symb_s dest, struct symb_s scope)
|
||||
{
|
||||
if (label)
|
||||
compile_codelabel(label);
|
||||
|
||||
|
||||
/* Fill in the basics of the %fork in the instruction. */
|
||||
vvp_code_t code = codespace_allocate();
|
||||
code->opcode = of_FORK;
|
||||
|
||||
/* Figure out the target PC. */
|
||||
code_label_lookup(code, dest.text);
|
||||
|
||||
/* Figure out the target SCOPE. */
|
||||
compile_vpi_lookup(&code->handle, scope.text);
|
||||
}
|
||||
|
||||
void compile_file_line(char*label, long file_idx, long lineno,
|
||||
char*description)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -339,8 +339,11 @@ extern void functor_ref_lookup(vvp_net_t**ref, char*lab);
|
|||
* code points to a code structure that points to the instruction
|
||||
* field that receives the result, and the label is the name to
|
||||
* lookup. The lookup will free the label text when it is done.
|
||||
*
|
||||
* The cptr2 flag tells the lookup to write the code pointer into the
|
||||
* cptr2 member of the code, instead of the cptr member.
|
||||
*/
|
||||
extern void code_label_lookup(struct vvp_code_s *code, char *label);
|
||||
extern void code_label_lookup(struct vvp_code_s *code, char *label, bool cptr2);
|
||||
|
||||
/*
|
||||
* The `compile_udp_def' function creates a UDP. The `table' is a
|
||||
|
|
@ -434,7 +437,6 @@ struct comp_operands_s {
|
|||
typedef struct comp_operands_s*comp_operands_t;
|
||||
|
||||
extern void compile_code(char*label, char*mnem, comp_operands_t opa);
|
||||
extern void compile_disable(char*label, struct symb_s symb);
|
||||
|
||||
extern void compile_file_line(char*label, long file_idx, long lineno,
|
||||
char*description);
|
||||
|
|
@ -460,8 +462,6 @@ extern void compile_vpi_func_call(char*label, char*name,
|
|||
unsigned string_stack);
|
||||
extern void print_vpi_call_errors();
|
||||
|
||||
extern void compile_fork(char*label, struct symb_s targ_s,
|
||||
struct symb_s scope_s);
|
||||
extern void compile_codelabel(char*label);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -234,8 +234,6 @@ static char* strdupnew(char const *str)
|
|||
"%vpi_call/i" { return K_vpi_call_i; }
|
||||
"%vpi_func" { return K_vpi_func; }
|
||||
"%vpi_func/r" { return K_vpi_func_r; }
|
||||
"%disable" { return K_disable; }
|
||||
"%fork" { return K_fork; }
|
||||
"%file_line" { return K_file_line; }
|
||||
|
||||
/* Handle the specialized variable access functions. */
|
||||
|
|
|
|||
10
vvp/parse.y
10
vvp/parse.y
|
|
@ -101,7 +101,6 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
|
||||
%token K_vpi_call K_vpi_call_w K_vpi_call_i
|
||||
%token K_vpi_func K_vpi_func_r
|
||||
%token K_disable K_fork
|
||||
%token K_ivl_version K_ivl_delay_selection
|
||||
%token K_vpi_module K_vpi_time_precision K_file_names K_file_line
|
||||
%token K_PORT_INPUT K_PORT_OUTPUT K_PORT_INOUT K_PORT_MIXED K_PORT_NODIR
|
||||
|
|
@ -664,15 +663,6 @@ statement
|
|||
{ compile_vpi_func_call($1, $5, -vpiRealVal, 0, $3, $4,
|
||||
$6.argc, $6.argv, $8, $9, $10); }
|
||||
|
||||
/* %disable statements are instructions that takes a scope reference
|
||||
as an operand. It therefore is parsed uniquely. */
|
||||
|
||||
| label_opt K_disable symbol ';'
|
||||
{ compile_disable($1, $3); }
|
||||
|
||||
|
||||
| label_opt K_fork symbol ',' symbol ';'
|
||||
{ compile_fork($1, $3, $5); }
|
||||
|
||||
/* Scope statements come in two forms. There are the scope
|
||||
declaration and the scope recall. The declarations create the
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class vvp_fun_part_aa : public vvp_fun_part, public automatic_hooks_s {
|
|||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
__vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ class vvp_fun_part_var_aa : public vvp_fun_part_var, public automatic_hooks_s {
|
|||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
__vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
ufunc_core::ufunc_core(unsigned owid, vvp_net_t*ptr,
|
||||
unsigned nports, vvp_net_t**ports,
|
||||
vvp_code_t sa, struct __vpiScope*call_scope__,
|
||||
vvp_code_t sa, __vpiScope*call_scope__,
|
||||
char*result_label, char*scope_label)
|
||||
: vvp_wide_fun_core(ptr, nports)
|
||||
{
|
||||
|
|
@ -168,7 +168,7 @@ void compile_ufunc(char*label, char*code, unsigned wid,
|
|||
to the ports list. */
|
||||
assert(argc == portc);
|
||||
|
||||
struct __vpiScope*call_scope = vpip_peek_current_scope();
|
||||
__vpiScope*call_scope = vpip_peek_current_scope();
|
||||
assert(call_scope);
|
||||
|
||||
/* Construct some phantom code that is the thread of the
|
||||
|
|
@ -188,7 +188,7 @@ void compile_ufunc(char*label, char*code, unsigned wid,
|
|||
|
||||
vvp_code_t exec_code = codespace_allocate();
|
||||
exec_code->opcode = of_EXEC_UFUNC;
|
||||
code_label_lookup(exec_code, code);
|
||||
code_label_lookup(exec_code, code, false);
|
||||
|
||||
vvp_code_t reap_code = codespace_allocate();
|
||||
reap_code->opcode = of_REAP_UFUNC;
|
||||
|
|
|
|||
12
vvp/ufunc.h
12
vvp/ufunc.h
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
# include "config.h"
|
||||
|
||||
class __vpiScope;
|
||||
|
||||
/*
|
||||
* The .ufunc statement creates functors to represent user defined
|
||||
* functions within the netlist (as opposed to within behavioral
|
||||
|
|
@ -53,13 +55,13 @@ class ufunc_core : public vvp_wide_fun_core {
|
|||
ufunc_core(unsigned ow, vvp_net_t*ptr,
|
||||
unsigned nports, vvp_net_t**ports,
|
||||
vvp_code_t start_address,
|
||||
struct __vpiScope*call_scope,
|
||||
__vpiScope*call_scope,
|
||||
char*result_label,
|
||||
char*scope_label);
|
||||
~ufunc_core();
|
||||
|
||||
struct __vpiScope*call_scope() { return call_scope_; }
|
||||
struct __vpiScope*func_scope() { return func_scope_; }
|
||||
__vpiScope*call_scope() { return call_scope_; }
|
||||
__vpiScope*func_scope() { return func_scope_; }
|
||||
|
||||
void assign_bits_to_ports(vvp_context_t context);
|
||||
void finish_thread();
|
||||
|
|
@ -85,8 +87,8 @@ class ufunc_core : public vvp_wide_fun_core {
|
|||
// This is a thread to execute the behavioral portion of the
|
||||
// function.
|
||||
vthread_t thread_;
|
||||
struct __vpiScope*call_scope_;
|
||||
struct __vpiScope*func_scope_;
|
||||
__vpiScope*call_scope_;
|
||||
__vpiScope*func_scope_;
|
||||
vvp_code_t code_;
|
||||
|
||||
// Where the result will be.
|
||||
|
|
|
|||
Loading…
Reference in New Issue