Add support for 64 bit delays in procedural non-blocking assignments.
This patch adds support for 64 bit non-blocking delays in procedural code. We fixed the procedural delay operator (blocking delays) earlier. This patch mostly mimics what was done there. The continuous assignment delay operator still needs to be fixed.
This commit is contained in:
parent
93ad8ff95f
commit
5ae86bd6b4
1
ivl.def
1
ivl.def
|
|
@ -39,6 +39,7 @@ ivl_expr_type
|
|||
ivl_expr_bits
|
||||
ivl_expr_branch
|
||||
ivl_expr_def
|
||||
ivl_expr_delay_val
|
||||
ivl_expr_dvalue
|
||||
ivl_expr_event
|
||||
ivl_expr_file
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __ivl_target_H
|
||||
#define __ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -211,6 +211,7 @@ typedef enum ivl_expr_type_e {
|
|||
IVL_EX_BACCESS= 19,
|
||||
IVL_EX_BINARY = 2,
|
||||
IVL_EX_CONCAT = 3,
|
||||
IVL_EX_DELAY = 20,
|
||||
IVL_EX_EVENT = 17,
|
||||
IVL_EX_MEMORY = 4,
|
||||
IVL_EX_NUMBER = 5,
|
||||
|
|
@ -749,6 +750,8 @@ extern const char* ivl_expr_bits(ivl_expr_t net);
|
|||
extern ivl_branch_t ivl_expr_branch(ivl_expr_t net);
|
||||
/* IVL_EX_UFUNC */
|
||||
extern ivl_scope_t ivl_expr_def(ivl_expr_t net);
|
||||
/* IVL_EX_DELAY */
|
||||
extern uint64_t ivl_expr_delay_val(ivl_expr_t net);
|
||||
/* IVL_EX_REALNUM */
|
||||
extern double ivl_expr_dvalue(ivl_expr_t net);
|
||||
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */
|
||||
|
|
|
|||
10
t-dll-api.cc
10
t-dll-api.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -309,6 +309,12 @@ extern "C" ivl_scope_t ivl_expr_def(ivl_expr_t net)
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern "C" uint64_t ivl_expr_delay_val(ivl_expr_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_EX_DELAY);
|
||||
return net->u_.delay_.value;
|
||||
}
|
||||
|
||||
extern "C" double ivl_expr_dvalue(ivl_expr_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_EX_REALNUM);
|
||||
|
|
@ -2137,7 +2143,7 @@ extern "C" ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net)
|
|||
extern "C" uint64_t ivl_stmt_delay_val(ivl_statement_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_ST_DELAY);
|
||||
return net->u_.delay_.delay_;
|
||||
return net->u_.delay_.value;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_stmt_nevent(ivl_statement_t net)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -249,10 +249,10 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
|
|||
if (const NetEConst*delay_num = dynamic_cast<const NetEConst*>(delay_exp)) {
|
||||
verinum val = delay_num->value();
|
||||
ivl_expr_t de = new struct ivl_expr_s;
|
||||
de->type_ = IVL_EX_ULONG;
|
||||
de->width_ = 8 * sizeof(unsigned long);
|
||||
de->type_ = IVL_EX_DELAY;
|
||||
de->width_ = 8 * sizeof(uint64_t);
|
||||
de->signed_ = 0;
|
||||
de->u_.ulong_.value = val.as_ulong();
|
||||
de->u_.delay_.value = val.as_ulong64();
|
||||
stmt_cur_->u_.assign_.delay = de;
|
||||
|
||||
} else if (delay_exp != 0) {
|
||||
|
|
@ -563,7 +563,7 @@ bool dll_target::proc_delay(const NetPDelay*net)
|
|||
} else {
|
||||
stmt_cur_->type_ = IVL_ST_DELAY;
|
||||
stmt_cur_->u_.delay_.stmt_ = tmp;
|
||||
stmt_cur_->u_.delay_.delay_ = net->delay();
|
||||
stmt_cur_->u_.delay_.value = net->delay();
|
||||
}
|
||||
|
||||
ivl_statement_t save_cur_ = stmt_cur_;
|
||||
|
|
|
|||
6
t-dll.h
6
t-dll.h
|
|
@ -291,6 +291,10 @@ struct ivl_expr_s {
|
|||
ivl_expr_t sub_;
|
||||
} unary_;
|
||||
|
||||
struct {
|
||||
uint64_t value;
|
||||
} delay_;
|
||||
|
||||
} u_;
|
||||
};
|
||||
|
||||
|
|
@ -714,7 +718,7 @@ struct ivl_statement_s {
|
|||
} contrib_;
|
||||
|
||||
struct { /* IVL_ST_DELAY */
|
||||
uint64_t delay_;
|
||||
uint64_t value;
|
||||
ivl_statement_t stmt_;
|
||||
} delay_;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2005-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -64,7 +64,7 @@ static int draw_number_bool64(ivl_expr_t expr)
|
|||
int res;
|
||||
const char*bits = ivl_expr_bits(expr);
|
||||
uint64_t val = 0;
|
||||
unsigned long idx;
|
||||
unsigned long idx, low, hig;
|
||||
|
||||
for (idx = 0 ; idx < ivl_expr_width(expr) ; idx += 1) {
|
||||
if (bits[idx] == '1')
|
||||
|
|
@ -72,7 +72,9 @@ static int draw_number_bool64(ivl_expr_t expr)
|
|||
}
|
||||
|
||||
res = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %d, %" PRIu64 ";\n", res, val);
|
||||
low = val % UINT64_C(0x100000000);
|
||||
hig = val / UINT64_C(0x100000000);
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n", res, low, hig);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -62,7 +62,8 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid, int negative_ok_flag)
|
|||
unsigned idx;
|
||||
|
||||
if (ivl_expr_type(ex) != IVL_EX_NUMBER
|
||||
&& ivl_expr_type(ex) != IVL_EX_ULONG)
|
||||
&& ivl_expr_type(ex) != IVL_EX_ULONG
|
||||
&& ivl_expr_type(ex) != IVL_EX_DELAY)
|
||||
return 0;
|
||||
|
||||
if (ivl_expr_type(ex) == IVL_EX_ULONG) {
|
||||
|
|
@ -74,6 +75,12 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid, int negative_ok_flag)
|
|||
else return 0;
|
||||
}
|
||||
|
||||
if (ivl_expr_type(ex) == IVL_EX_DELAY) {
|
||||
if (lim_wid >= 8*sizeof(uint64_t)) return 1;
|
||||
/* For now we only support this as a 64 bit value. */
|
||||
else return 0;
|
||||
}
|
||||
|
||||
bits = ivl_expr_bits(ex);
|
||||
|
||||
if (ivl_expr_signed(ex) && bits[nbits-1]=='1')
|
||||
|
|
@ -134,10 +141,10 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
|||
assert(number_is_immediate(expr, IMM_WID, 1));
|
||||
long imm = get_number_immediate(expr);
|
||||
if (imm >= 0) {
|
||||
fprintf(vvp_out, " %%ix/load %u, %ld;\n", ix, imm);
|
||||
fprintf(vvp_out, " %%ix/load %u, %ld, 0;\n", ix, imm);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/load %u, 0; loading %ld\n", ix, imm);
|
||||
fprintf(vvp_out, " %%ix/sub %u, %ld;\n", ix, -imm);
|
||||
fprintf(vvp_out, " %%ix/load %u, 0, 0; loading %ld\n", ix, imm);
|
||||
fprintf(vvp_out, " %%ix/sub %u, %ld, 0;\n", ix, -imm);
|
||||
}
|
||||
/* This can not have have a X/Z value so clear bit 4. */
|
||||
fprintf(vvp_out, " %%mov 4, 0, 1;\n");
|
||||
|
|
@ -1200,6 +1207,7 @@ static struct vector_info draw_load_add_immediate(ivl_expr_t le,
|
|||
{
|
||||
struct vector_info lv;
|
||||
long imm = get_number_immediate(re);
|
||||
assert(number_is_immediate(re, IMM_WID, 1));
|
||||
lv.base = allocate_vector(wid);
|
||||
lv.wid = wid;
|
||||
if (lv.base == 0) {
|
||||
|
|
@ -2094,7 +2102,7 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
|
|||
const char*sign_flag = (add_index>0)? "/s" : "";
|
||||
|
||||
/* Add an immediate value to an array value. */
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate);
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu, 0;\n", immediate);
|
||||
fprintf(vvp_out, " %%load/avp0%s %u, v%p, %u;\n",
|
||||
sign_flag, res.base, sig, res.wid);
|
||||
}
|
||||
|
|
@ -2117,10 +2125,10 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
|
|||
|
||||
/* If this is a REG (a variable) then I can do a vector read. */
|
||||
if (immediate >= 0) {
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate);
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu, 0;\n", immediate);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/load 0, 0; immediate=%ld\n", immediate);
|
||||
fprintf(vvp_out, " %%ix/sub 0, %ld;\n", -immediate);
|
||||
fprintf(vvp_out, " %%ix/load 0, 0, 0; immediate=%ld\n", immediate);
|
||||
fprintf(vvp_out, " %%ix/sub 0, %ld, 0;\n", -immediate);
|
||||
}
|
||||
fprintf(vvp_out, " %%load/vp0%s %u, v%p_%u, %u;\n", sign_flag,
|
||||
res.base, sig,word, res.wid);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -77,7 +77,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off = 0;
|
||||
unsigned long part_off = 0;
|
||||
|
||||
/* Although Verilog doesn't support it, we'll handle
|
||||
here the case of an l-value part select of an array
|
||||
|
|
@ -87,7 +87,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, 64, 0)) {
|
||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
draw_eval_expr_into_integer(word_ix, 3);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu;\n", use_word);
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu, 0;\n", use_word);
|
||||
}
|
||||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
|
|
@ -147,9 +147,9 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
draw_eval_expr_into_integer(word_ix, 3);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu;\n", use_word);
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu, 0;\n", use_word);
|
||||
}
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%ix/load 1, %lu, 0;\n", part_off);
|
||||
fprintf(vvp_out, " %%set/av v%p, %u, %u;\n",
|
||||
sig, bit, wid);
|
||||
if (word_ix) /* Only need this label if word_ix is set. */
|
||||
|
|
@ -164,7 +164,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
/* If the word index is a constant, then we can write
|
||||
directly to the word and save the index calculation. */
|
||||
if (word_ix == 0) {
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu, 0;\n", part_off);
|
||||
fprintf(vvp_out, " %%set/x0 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, bit, wid);
|
||||
|
||||
|
|
@ -173,7 +173,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
unsigned index_reg = 3;
|
||||
draw_eval_expr_into_integer(word_ix, index_reg);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%ix/load 1, %lu, 0;\n", part_off);
|
||||
fprintf(vvp_out, " %%set/av v%p, %u, %u;\n",
|
||||
sig, bit, wid);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
|
|
@ -188,8 +188,8 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
directly to the word and save the index calculation. */
|
||||
if (word_ix == 0) {
|
||||
if (use_word < ivl_signal_array_count(sig)) {
|
||||
fprintf(vvp_out, " %%ix/load 1, 0;\n");
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu;\n", use_word);
|
||||
fprintf(vvp_out, " %%ix/load 1, 0, 0;\n");
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu, 0;\n", use_word);
|
||||
fprintf(vvp_out, " %%set/av v%p, %u, %u;\n",
|
||||
sig, bit, wid);
|
||||
} else {
|
||||
|
|
@ -202,7 +202,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
unsigned index_reg = 3;
|
||||
draw_eval_expr_into_integer(word_ix, index_reg);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
fprintf(vvp_out, " %%ix/load 1, 0;\n");
|
||||
fprintf(vvp_out, " %%ix/load 1, 0, 0;\n");
|
||||
fprintf(vvp_out, " %%set/av v%p, %u, %u;\n",
|
||||
sig, bit, wid);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
|
|
@ -223,23 +223,23 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
}
|
||||
|
||||
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
unsigned bit, unsigned delay, ivl_expr_t dexp,
|
||||
unsigned bit, uint64_t delay, ivl_expr_t dexp,
|
||||
ivl_expr_t part_off_ex, unsigned width,
|
||||
unsigned nevents)
|
||||
{
|
||||
unsigned skip_assign = transient_id++;
|
||||
|
||||
unsigned part_off = 0;
|
||||
unsigned long part_off = 0;
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, 64, 0)) {
|
||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
||||
/* This code is common to all the different types of array delays. */
|
||||
if (number_is_immediate(word_ix, 64, 0)) {
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu; address\n",
|
||||
if (number_is_immediate(word_ix, IMM_WID, 0)) {
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
|
||||
get_number_immediate(word_ix));
|
||||
} else {
|
||||
/* Calculate array word index into index register 3 */
|
||||
|
|
@ -248,14 +248,14 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
|||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
}
|
||||
/* Store expression width into index word 0 */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u; word width\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0; word width\n", width);
|
||||
if (part_off_ex) {
|
||||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
} else {
|
||||
/* Store word part select into index 1 */
|
||||
fprintf(vvp_out, " %%ix/load 1, %u; part off\n", part_off);
|
||||
fprintf(vvp_out, " %%ix/load 1, %lu, 0; part off\n", part_off);
|
||||
}
|
||||
|
||||
if (dexp != 0) {
|
||||
|
|
@ -270,8 +270,24 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
|||
fprintf(vvp_out, " %%assign/av/e v%p, %u;\n", lsig, bit);
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
fprintf(vvp_out, " %%assign/av v%p, %u, %u;\n", lsig,
|
||||
delay, bit);
|
||||
unsigned long low_d = delay % UINT64_C(0x100000000);
|
||||
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
||||
|
||||
/*
|
||||
* The %assign can only take a 32 bit delay. For a larger
|
||||
* delay we need to put it into an index register.
|
||||
*/
|
||||
if (hig_d != 0) {
|
||||
int delay_index = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
||||
delay_index, low_d, hig_d);
|
||||
fprintf(vvp_out, " %%assign/av/d v%p, %d, %u;\n", lsig,
|
||||
delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%assign/av v%p, %lu, %u;\n",
|
||||
lsig, low_d, bit);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
|
|
@ -281,12 +297,12 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
|||
}
|
||||
|
||||
static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
||||
unsigned delay, ivl_expr_t dexp,
|
||||
uint64_t delay, ivl_expr_t dexp,
|
||||
unsigned width, unsigned nevents)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off = 0;
|
||||
unsigned long part_off = 0;
|
||||
|
||||
ivl_expr_t word_ix = ivl_lval_idx(lval);
|
||||
const unsigned long use_word = 0;
|
||||
|
|
@ -300,7 +316,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, 64, 0)) {
|
||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
|
@ -308,6 +324,9 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
if (ivl_lval_mux(lval))
|
||||
part_off_ex = ivl_lval_mux(lval);
|
||||
|
||||
unsigned long low_d = delay % UINT64_C(0x100000000);
|
||||
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
||||
|
||||
if (part_off_ex) {
|
||||
unsigned skip_assign = transient_id++;
|
||||
if (dexp != 0) {
|
||||
|
|
@ -317,8 +336,8 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/x1/d v%p_%lu, %d, %u;\n",
|
||||
sig, use_word, delay_index, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
clr_word(delay_index);
|
||||
|
|
@ -327,7 +346,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/x1/e v%p_%lu, %u;\n",
|
||||
sig, use_word, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
|
|
@ -337,9 +356,24 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
/*
|
||||
* The %assign can only take a 32 bit delay. For a larger
|
||||
* delay we need to put it into an index register.
|
||||
*/
|
||||
if (hig_d != 0) {
|
||||
int delay_index = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
||||
delay_index, low_d, hig_d);
|
||||
fprintf(vvp_out,
|
||||
" %%assign/v0/x1/d v%p_%lu, %d, %u;\n",
|
||||
sig, use_word, delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else {
|
||||
fprintf(vvp_out,
|
||||
" %%assign/v0/x1 v%p_%lu, %lu, %u;\n",
|
||||
sig, use_word, low_d, bit);
|
||||
}
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
}
|
||||
|
||||
|
|
@ -353,41 +387,71 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
/* Calculated delay... */
|
||||
int delay_index = allocate_word();
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %lu, 0;\n", part_off);
|
||||
fprintf(vvp_out, " %%assign/v0/x1/d v%p_%lu, %d, %u;\n",
|
||||
sig, use_word, delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else if (nevents != 0) {
|
||||
/* Event control delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %lu, 0;\n", part_off);
|
||||
fprintf(vvp_out, " %%assign/v0/x1/e v%p_%lu, %u;\n",
|
||||
sig, use_word, bit);
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %lu, 0;\n", part_off);
|
||||
/*
|
||||
* The %assign can only take a 32 bit delay. For a larger
|
||||
* delay we need to put it into an index register.
|
||||
*/
|
||||
if (hig_d != 0) {
|
||||
int delay_index = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
||||
delay_index, low_d, hig_d);
|
||||
fprintf(vvp_out,
|
||||
" %%assign/v0/x1/d v%p_%lu, %d, %u;\n",
|
||||
sig, use_word, delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else {
|
||||
fprintf(vvp_out,
|
||||
" %%assign/v0/x1 v%p_%lu, %lu, %u;\n",
|
||||
sig, use_word, low_d, bit);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (dexp != 0) {
|
||||
/* Calculated delay... */
|
||||
draw_eval_expr_into_integer(dexp, 1);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/d v%p_%lu, 1, %u;\n",
|
||||
sig, use_word, bit);
|
||||
int delay_index = allocate_word();
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/d v%p_%lu, %d, %u;\n",
|
||||
sig, use_word, delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else if (nevents != 0) {
|
||||
/* Event control delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/e v%p_%lu, %u;\n",
|
||||
sig, use_word, bit);
|
||||
} else {
|
||||
/* Constant delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
||||
/*
|
||||
* The %assign can only take a 32 bit delay. For a larger
|
||||
* delay we need to put it into an index register.
|
||||
*/
|
||||
if (hig_d != 0) {
|
||||
int delay_index = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
||||
delay_index, low_d, hig_d);
|
||||
fprintf(vvp_out, " %%assign/v0/d v%p_%lu, %d, %u;\n",
|
||||
sig, use_word, delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%assign/v0 v%p_%lu, %lu, %u;\n",
|
||||
sig, use_word, low_d, bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -569,7 +633,7 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
|||
unsigned long use_word = 0;
|
||||
/* thread address for a word value. */
|
||||
int word;
|
||||
unsigned long delay = 0;
|
||||
uint64_t delay = 0;
|
||||
unsigned nevents = ivl_stmt_nevent(net);
|
||||
|
||||
/* Must be exactly 1 l-value. */
|
||||
|
|
@ -586,9 +650,9 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
|||
use_word = get_number_immediate(word_ix);
|
||||
}
|
||||
|
||||
if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) {
|
||||
assert(number_is_immediate(del, IMM_WID, 0));
|
||||
delay = ivl_expr_uvalue(del);
|
||||
if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
|
||||
assert(number_is_immediate(del, 64, 0));
|
||||
delay = ivl_expr_delay_val(del);
|
||||
del = 0;
|
||||
}
|
||||
|
||||
|
|
@ -607,8 +671,24 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%assign/wr/e v%p_%lu, %u;\n",
|
||||
sig, use_word, word);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%assign/wr v%p_%lu, %lu, %u;\n",
|
||||
sig, use_word, delay, word);
|
||||
unsigned long low_d = delay % UINT64_C(0x100000000);
|
||||
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
||||
|
||||
/*
|
||||
* The %assign can only take a 32 bit delay. For a larger
|
||||
* delay we need to put it into an index register.
|
||||
*/
|
||||
if (hig_d != 0) {
|
||||
int delay_index = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
||||
delay_index, low_d, hig_d);
|
||||
fprintf(vvp_out, " %%assign/wr/d v%p_%lu, %d, %u;\n",
|
||||
sig, use_word, delay_index, word);
|
||||
clr_word(delay_index);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%assign/wr v%p_%lu, %lu, %u;\n",
|
||||
sig, use_word, low_d, word);
|
||||
}
|
||||
}
|
||||
|
||||
clr_word(word);
|
||||
|
|
@ -669,7 +749,7 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
assert(ivl_stmt_cond_expr(net) == 0);
|
||||
}
|
||||
|
||||
unsigned long delay = 0;
|
||||
uint64_t delay = 0;
|
||||
|
||||
/* Detect special cases that are handled elsewhere. */
|
||||
lval = ivl_stmt_lval(net,0);
|
||||
|
|
@ -682,9 +762,9 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
}
|
||||
}
|
||||
|
||||
if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) {
|
||||
assert(number_is_immediate(del, IMM_WID, 0));
|
||||
delay = ivl_expr_uvalue(del);
|
||||
if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
|
||||
assert(number_is_immediate(del, 64, 0));
|
||||
delay = ivl_expr_delay_val(del);
|
||||
del = 0;
|
||||
}
|
||||
|
||||
|
|
@ -1017,14 +1097,14 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
|||
|
||||
unsigned use_wid = ivl_lval_width(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off;
|
||||
unsigned long part_off;
|
||||
ivl_expr_t word_idx = ivl_lval_idx(lval);
|
||||
unsigned long use_word = 0;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, 64, 0));
|
||||
assert(number_is_immediate(part_off_ex, IMM_WID, 0));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
}
|
||||
|
||||
|
|
@ -1039,7 +1119,7 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
|||
if (part_off != 0 || use_wid != ivl_signal_width(lsig)) {
|
||||
|
||||
command_name = command_name_x0;
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu, 0;\n", part_off);
|
||||
|
||||
} else {
|
||||
/* Do not support bit or part selects of l-values yet. */
|
||||
|
|
|
|||
|
|
@ -133,18 +133,18 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%evctl/s",of_EVCTLS, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%force/link",of_FORCE_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
|
||||
{ "%force/v",of_FORCE_V,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%force/wr",of_FORCE_WR,2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%force/wr",of_FORCE_WR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%force/x0",of_FORCE_X0,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%free", of_FREE, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%ix/add", of_IX_ADD, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
|
||||
{ "%ix/add", of_IX_ADD, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
||||
{ "%ix/get", of_IX_GET, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%ix/get/s",of_IX_GET_S,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%ix/getv",of_IX_GETV,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
||||
{ "%ix/getv/s",of_IX_GETVS,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
||||
{ "%ix/load",of_IX_LOAD,2, {OA_BIT1, OA_NUMBER, OA_NONE} },
|
||||
{ "%ix/mul", of_IX_MUL, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
|
||||
{ "%ix/sub", of_IX_SUB, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
|
||||
{ "%ix/getv/s",of_IX_GETVS,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
||||
{ "%ix/load",of_IX_LOAD,3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
||||
{ "%ix/mul", of_IX_MUL, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
||||
{ "%ix/sub", of_IX_SUB, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
|
||||
{ "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -417,22 +417,25 @@ These instructions are like the %ix/get instructions, except that they
|
|||
read directly from a functor label instead of from thread bits. They
|
||||
set bit 4 just like %ix/get.
|
||||
|
||||
* %ix/load <idx>, <value>
|
||||
* %ix/load <idx>, <low> <high>
|
||||
|
||||
This instruction loads an immediate value into the addressed index
|
||||
register. The index register holds numeric values, so the <value> is a
|
||||
number. The idx value selects the index register. This is different
|
||||
from %ix/get, which loads the index register from a value in the
|
||||
thread bit vector. The value is a signed decimal value >= 0.
|
||||
register. The index register holds signed 64 bit numeric values, so
|
||||
<low> and <high> are used to separate the value in two 32 bit chunks.
|
||||
The idx value selects the index register. This is different from
|
||||
%ix/get, which loads the index register from a value in the thread bit
|
||||
vector. The values are unsigned decimal values and are combined as
|
||||
<high> << 32 | <low> to produce the final value.
|
||||
|
||||
|
||||
* %ix/add <idx>, <value>
|
||||
* %ix/sub <idx>, <value>
|
||||
* %ix/mul <idx>, <value>
|
||||
* %ix/add <idx>, <low> <high>
|
||||
* %ix/sub <idx>, <low> <high>
|
||||
* %ix/mul <idx>, <low> <high>
|
||||
|
||||
This instruction adds, subtracts, or multiplies an immediate value to
|
||||
the addressed index register. The index register holds numeric values,
|
||||
so the <value> is a number. The <idx> value selects the index register.
|
||||
These instructions add, subtract, or multiply the selected index
|
||||
register by the immediate value. The 64 bit immediate value is built
|
||||
from the two 32 bit chunks <low> and <high> (see %ix/load above).
|
||||
The <idx> value selects the index register.
|
||||
|
||||
|
||||
* %jmp <code-label>
|
||||
|
|
|
|||
|
|
@ -862,7 +862,7 @@ bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t cp)
|
|||
unsigned wid = thr->words[0].w_int;
|
||||
long off = thr->words[1].w_int;
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
unsigned long delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
long vwidth = get_array_word_size(cp->array);
|
||||
|
|
@ -956,7 +956,7 @@ bool of_ASSIGN_V0D(vthread_t thr, vvp_code_t cp)
|
|||
unsigned wid = thr->words[0].w_int;
|
||||
assert(wid > 0);
|
||||
|
||||
unsigned long delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
|
|
@ -1044,7 +1044,7 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
long off = thr->words[1].w_int;
|
||||
unsigned delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
vvp_fun_signal_vec*sig
|
||||
|
|
@ -1152,7 +1152,7 @@ bool of_ASSIGN_WR(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
bool of_ASSIGN_WRD(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
|
||||
unsigned index = cp->bit_idx[1];
|
||||
s_vpi_time del;
|
||||
|
||||
|
|
@ -2554,30 +2554,44 @@ bool of_INV(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
|
||||
/*
|
||||
** Index registers, unsigned arithmetic.
|
||||
*/
|
||||
* Index registers, arithmetic.
|
||||
*/
|
||||
|
||||
static inline int64_t get_as_64_bit(uint32_t low_32, uint32_t high_32)
|
||||
{
|
||||
int64_t low = low_32;
|
||||
int64_t res = high_32;
|
||||
|
||||
res <<= 32;
|
||||
res |= low;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool of_IX_ADD(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
thr->words[cp->bit_idx[0]].w_int += cp->number;
|
||||
return true;
|
||||
thr->words[cp->number].w_int += get_as_64_bit(cp->bit_idx[0],
|
||||
cp->bit_idx[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_IX_SUB(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
thr->words[cp->bit_idx[0]].w_int -= cp->number;
|
||||
return true;
|
||||
thr->words[cp->number].w_int -= get_as_64_bit(cp->bit_idx[0],
|
||||
cp->bit_idx[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_IX_MUL(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
thr->words[cp->bit_idx[0]].w_int *= cp->number;
|
||||
return true;
|
||||
thr->words[cp->number].w_int *= get_as_64_bit(cp->bit_idx[0],
|
||||
cp->bit_idx[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_IX_LOAD(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
thr->words[cp->bit_idx[0]].w_int = cp->number;
|
||||
thr->words[cp->number].w_int = get_as_64_bit(cp->bit_idx[0],
|
||||
cp->bit_idx[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue