Add support for non-blocking assignment to real arrays.
This patch adds support for the various types of non-blocking assignments to real arrays.
This commit is contained in:
parent
9d765820bf
commit
9a4cd1af32
|
|
@ -224,6 +224,63 @@ static void set_to_lvariable(ivl_lval_t lval,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Support a non-blocking assignment to a real array word. */
|
||||||
|
static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
|
unsigned bit, uint64_t delay,
|
||||||
|
ivl_expr_t dexp, unsigned nevents)
|
||||||
|
{
|
||||||
|
unsigned skip_assign = transient_id++;
|
||||||
|
|
||||||
|
/* This code is common to all the different types of array delays. */
|
||||||
|
if (number_is_immediate(word_ix, IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(word_ix));
|
||||||
|
fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
|
||||||
|
get_number_immediate(word_ix));
|
||||||
|
} else {
|
||||||
|
/* Calculate array word index into index register 3 */
|
||||||
|
draw_eval_expr_into_integer(word_ix, 3);
|
||||||
|
/* Skip assignment if word expression is not defined. */
|
||||||
|
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dexp != 0) {
|
||||||
|
/* Calculated delay... */
|
||||||
|
int delay_index = allocate_word();
|
||||||
|
draw_eval_expr_into_integer(dexp, delay_index);
|
||||||
|
fprintf(vvp_out, " %%assign/ar/d v%p, %d, %u;\n", lsig,
|
||||||
|
delay_index, bit);
|
||||||
|
clr_word(delay_index);
|
||||||
|
} else if (nevents != 0) {
|
||||||
|
/* Event control delay... */
|
||||||
|
fprintf(vvp_out, " %%assign/ar/e v%p, %u;\n", lsig, bit);
|
||||||
|
} else {
|
||||||
|
/* Constant delay... */
|
||||||
|
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/ar/d v%p, %d, %u;\n", lsig,
|
||||||
|
delay_index, bit);
|
||||||
|
clr_word(delay_index);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%assign/ar v%p, %lu, %u;\n",
|
||||||
|
lsig, low_d, bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||||
|
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
|
||||||
|
|
||||||
|
clear_expression_lookaside();
|
||||||
|
}
|
||||||
|
|
||||||
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
unsigned bit, uint64_t delay, ivl_expr_t dexp,
|
unsigned bit, uint64_t delay, ivl_expr_t dexp,
|
||||||
ivl_expr_t part_off_ex, unsigned width,
|
ivl_expr_t part_off_ex, unsigned width,
|
||||||
|
|
@ -648,21 +705,6 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
||||||
sig = ivl_lval_sig(lval);
|
sig = ivl_lval_sig(lval);
|
||||||
assert(sig);
|
assert(sig);
|
||||||
|
|
||||||
if (ivl_signal_dimensions(sig) > 0) {
|
|
||||||
word_ix = ivl_lval_idx(lval);
|
|
||||||
assert(word_ix);
|
|
||||||
assert(number_is_immediate(word_ix, IMM_WID, 0));
|
|
||||||
assert(! number_is_unknown(word_ix));
|
|
||||||
use_word = get_number_immediate(word_ix);
|
|
||||||
/* This method no longer works since variable arrays do not
|
|
||||||
* support <variable_id>_<idx> access any more. We need real
|
|
||||||
* array specific opcodes (%assign/ar, etc.). */
|
|
||||||
fprintf(stderr, "%s:%u: vvp-tgt sorry: non-blocking assignment "
|
|
||||||
"to a real array word is not supported.\n",
|
|
||||||
ivl_expr_file(rval), ivl_expr_lineno(rval));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
|
if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
|
||||||
assert(number_is_immediate(del, 64, 0));
|
assert(number_is_immediate(del, 64, 0));
|
||||||
delay = ivl_expr_delay_val(del);
|
delay = ivl_expr_delay_val(del);
|
||||||
|
|
@ -672,6 +714,14 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
||||||
/* Evaluate the r-value */
|
/* Evaluate the r-value */
|
||||||
word = draw_eval_real(rval);
|
word = draw_eval_real(rval);
|
||||||
|
|
||||||
|
if (ivl_signal_dimensions(sig) > 0) {
|
||||||
|
word_ix = ivl_lval_idx(lval);
|
||||||
|
assert(word_ix);
|
||||||
|
assign_to_array_r_word(sig, word_ix, word, delay, del, nevents);
|
||||||
|
clr_word(word);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* We need to calculate the delay expression. */
|
/* We need to calculate the delay expression. */
|
||||||
if (del) {
|
if (del) {
|
||||||
assert(nevents == 0);
|
assert(nevents == 0);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __codes_H
|
#ifndef __codes_H
|
||||||
#define __codes_H
|
#define __codes_H
|
||||||
/*
|
/*
|
||||||
* 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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -40,6 +40,9 @@ extern bool of_ALLOC(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_AND(vthread_t thr, vvp_code_t code);
|
extern bool of_AND(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ANDI(vthread_t thr, vvp_code_t code);
|
extern bool of_ANDI(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ANDR(vthread_t thr, vvp_code_t code);
|
extern bool of_ANDR(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_ASSIGN_AR(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_ASSIGN_ARE(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t code);
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,9 @@ const static struct opcode_table_s opcode_table[] = {
|
||||||
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%andi", of_ANDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%andi", of_ANDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
|
{ "%assign/ar",of_ASSIGN_AR,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||||
|
{ "%assign/ar/d",of_ASSIGN_ARD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||||
|
{ "%assign/ar/e",of_ASSIGN_ARE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
|
||||||
{ "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
{ "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||||
{ "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
{ "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
|
||||||
{ "%assign/av/e",of_ASSIGN_AVE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
|
{ "%assign/av/e",of_ASSIGN_AVE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
|
||||||
|
|
|
||||||
26
vvp/event.cc
26
vvp/event.cc
|
|
@ -159,6 +159,32 @@ void schedule_evctl(vvp_array_t memory, unsigned index,
|
||||||
ep->last = &((*(ep->last))->next);
|
ep->last = &((*(ep->last))->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evctl_array_r::evctl_array_r(vvp_array_t memory, unsigned index,
|
||||||
|
double value, unsigned long ecount)
|
||||||
|
:evctl(ecount)
|
||||||
|
{
|
||||||
|
mem_ = memory;
|
||||||
|
idx_ = index;
|
||||||
|
value_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void evctl_array_r::run_run()
|
||||||
|
{
|
||||||
|
array_set_word(mem_, idx_, value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void schedule_evctl(vvp_array_t memory, unsigned index,
|
||||||
|
double value,
|
||||||
|
vvp_net_t*event, unsigned long ecount)
|
||||||
|
{
|
||||||
|
// Get the functor we are going to wait on.
|
||||||
|
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
|
||||||
|
assert(ep);
|
||||||
|
// Now add this call to the end of the event list.
|
||||||
|
*(ep->last) = new evctl_array_r(memory, index, value, ecount);
|
||||||
|
ep->last = &((*(ep->last))->next);
|
||||||
|
}
|
||||||
|
|
||||||
inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
|
inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
|
||||||
{
|
{
|
||||||
return 1 << ((from << 2) | to);
|
return 1 << ((from << 2) | to);
|
||||||
|
|
|
||||||
18
vvp/event.h
18
vvp/event.h
|
|
@ -81,6 +81,20 @@ class evctl_array : public evctl {
|
||||||
unsigned off_;
|
unsigned off_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class evctl_array_r : public evctl {
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit evctl_array_r(vvp_array_t memory, unsigned index,
|
||||||
|
double value, unsigned long ecount);
|
||||||
|
virtual ~evctl_array_r() {}
|
||||||
|
virtual void run_run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
vvp_array_t mem_;
|
||||||
|
unsigned idx_;
|
||||||
|
double value_;
|
||||||
|
};
|
||||||
|
|
||||||
extern void schedule_evctl(struct __vpiHandle*handle, double value,
|
extern void schedule_evctl(struct __vpiHandle*handle, double value,
|
||||||
vvp_net_t*event, unsigned long ecount);
|
vvp_net_t*event, unsigned long ecount);
|
||||||
|
|
||||||
|
|
@ -92,6 +106,10 @@ extern void schedule_evctl(vvp_array_t memory, unsigned index,
|
||||||
const vvp_vector4_t&value, unsigned offset,
|
const vvp_vector4_t&value, unsigned offset,
|
||||||
vvp_net_t*event, unsigned long ecount);
|
vvp_net_t*event, unsigned long ecount);
|
||||||
|
|
||||||
|
extern void schedule_evctl(vvp_array_t memory, unsigned index,
|
||||||
|
double value,
|
||||||
|
vvp_net_t*event, unsigned long ecount);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Event / edge detection functors
|
* Event / edge detection functors
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -422,6 +422,8 @@ int main(int argc, char*argv[])
|
||||||
count_assign_real_pool());
|
count_assign_real_pool());
|
||||||
vpi_mcd_printf(1, " ...assign(word) pool=%lu\n",
|
vpi_mcd_printf(1, " ...assign(word) pool=%lu\n",
|
||||||
count_assign_aword_pool());
|
count_assign_aword_pool());
|
||||||
|
vpi_mcd_printf(1, " ...assign(word/r) pool=%lu\n",
|
||||||
|
count_assign_arword_pool());
|
||||||
vpi_mcd_printf(1, " %8lu other events (pool=%lu)\n",
|
vpi_mcd_printf(1, " %8lu other events (pool=%lu)\n",
|
||||||
count_gen_events, count_gen_pool());
|
count_gen_events, count_gen_pool());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,26 @@ means the following:
|
||||||
1 and 1 --> 1
|
1 and 1 --> 1
|
||||||
otherwise x
|
otherwise x
|
||||||
|
|
||||||
|
* %assign/ar <array-label>, <delay>, <bit>
|
||||||
|
* %assign/ar/d <array-label>, <delayx>, <bit>
|
||||||
|
* %assign/ar/e <array-label>, <bit>
|
||||||
|
|
||||||
|
The %assign/ar instruction assigns a real value to a word in the
|
||||||
|
labeled real array. The <delay> is the delay in simulation time to
|
||||||
|
the assignment (0 for non-blocking assignment) and <bit> is the
|
||||||
|
index register that contains the value to write.
|
||||||
|
|
||||||
|
The memory word address is read from index register 3. The address is
|
||||||
|
in canonical form.
|
||||||
|
|
||||||
|
The %assign/ar/d variation reads the delay from an integer register that
|
||||||
|
is given by the <delayx> value. This should not be 3 or the <bit> index,
|
||||||
|
of course, since these registers contain the word address and the value.
|
||||||
|
|
||||||
|
The %assign/ar/e variation uses the information in the thread
|
||||||
|
event control registers to determine when to perform the assign.
|
||||||
|
%evctl is used to set the event control information.
|
||||||
|
|
||||||
* %assign/av <array-label>, <delay>, <bit>
|
* %assign/av <array-label>, <delay>, <bit>
|
||||||
* %assign/av/d <array-label>, <delayx>, <bit>
|
* %assign/av/d <array-label>, <delayx>, <bit>
|
||||||
* %assign/av/e <array-label>, <bit>
|
* %assign/av/e <array-label>, <bit>
|
||||||
|
|
@ -851,7 +871,7 @@ and leaves the result in the <dst> vector. xor is this:
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
|
||||||
|
|
@ -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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -257,6 +257,37 @@ void assign_array_word_s::operator delete(void*ptr)
|
||||||
|
|
||||||
unsigned long count_assign_aword_pool(void) { return array_w_heap.pool; }
|
unsigned long count_assign_aword_pool(void) { return array_w_heap.pool; }
|
||||||
|
|
||||||
|
struct assign_array_r_word_s : public event_s {
|
||||||
|
vvp_array_t mem;
|
||||||
|
unsigned adr;
|
||||||
|
double val;
|
||||||
|
void run_run(void);
|
||||||
|
|
||||||
|
static void* operator new(size_t);
|
||||||
|
static void operator delete(void*);
|
||||||
|
};
|
||||||
|
|
||||||
|
void assign_array_r_word_s::run_run(void)
|
||||||
|
{
|
||||||
|
count_assign_events += 1;
|
||||||
|
array_set_word(mem, adr, val);
|
||||||
|
}
|
||||||
|
static const size_t ARRAY_R_W_CHUNK_COUNT = 8192 / sizeof(struct assign_array_r_word_s);
|
||||||
|
static slab_t<sizeof(assign_array_r_word_s),ARRAY_R_W_CHUNK_COUNT> array_r_w_heap;
|
||||||
|
|
||||||
|
inline void* assign_array_r_word_s::operator new(size_t size)
|
||||||
|
{
|
||||||
|
assert(size == sizeof(assign_array_r_word_s));
|
||||||
|
return array_r_w_heap.alloc_slab();
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign_array_r_word_s::operator delete(void*ptr)
|
||||||
|
{
|
||||||
|
array_r_w_heap.free_slab(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long count_assign_arword_pool(void) { return array_r_w_heap.pool; }
|
||||||
|
|
||||||
struct generic_event_s : public event_s {
|
struct generic_event_s : public event_s {
|
||||||
vvp_gen_event_t obj;
|
vvp_gen_event_t obj;
|
||||||
bool delete_obj_when_done;
|
bool delete_obj_when_done;
|
||||||
|
|
@ -609,6 +640,18 @@ void schedule_assign_array_word(vvp_array_t mem,
|
||||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void schedule_assign_array_word(vvp_array_t mem,
|
||||||
|
unsigned word_addr,
|
||||||
|
double val,
|
||||||
|
vvp_time64_t delay)
|
||||||
|
{
|
||||||
|
struct assign_array_r_word_s*cur = new struct assign_array_r_word_s;
|
||||||
|
cur->mem = mem;
|
||||||
|
cur->adr = word_addr;
|
||||||
|
cur->val = val;
|
||||||
|
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||||
|
}
|
||||||
|
|
||||||
void schedule_set_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
void schedule_set_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||||
{
|
{
|
||||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);
|
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __schedule_H
|
#ifndef __schedule_H
|
||||||
#define __schedule_H
|
#define __schedule_H
|
||||||
/*
|
/*
|
||||||
* 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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -57,6 +57,11 @@ extern void schedule_assign_array_word(vvp_array_t mem,
|
||||||
unsigned off,
|
unsigned off,
|
||||||
vvp_vector4_t val,
|
vvp_vector4_t val,
|
||||||
vvp_time64_t delay);
|
vvp_time64_t delay);
|
||||||
|
|
||||||
|
extern void schedule_assign_array_word(vvp_array_t mem,
|
||||||
|
unsigned word_address,
|
||||||
|
double val,
|
||||||
|
vvp_time64_t delay);
|
||||||
/*
|
/*
|
||||||
* This is very similar to schedule_assign_vector, but generates an
|
* This is very similar to schedule_assign_vector, but generates an
|
||||||
* event in the active queue. It is used at link time to assign a
|
* event in the active queue. It is used at link time to assign a
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __statistics_H
|
#ifndef __statistics_H
|
||||||
#define __statistics_H
|
#define __statistics_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2007 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -47,6 +47,7 @@ extern unsigned long count_assign4_pool(void);
|
||||||
extern unsigned long count_assign8_pool(void);
|
extern unsigned long count_assign8_pool(void);
|
||||||
extern unsigned long count_assign_real_pool(void);
|
extern unsigned long count_assign_real_pool(void);
|
||||||
extern unsigned long count_assign_aword_pool(void);
|
extern unsigned long count_assign_aword_pool(void);
|
||||||
|
extern unsigned long count_assign_arword_pool(void);
|
||||||
|
|
||||||
extern unsigned long count_gen_events;
|
extern unsigned long count_gen_events;
|
||||||
extern unsigned long count_gen_pool(void);
|
extern unsigned long count_gen_pool(void);
|
||||||
|
|
|
||||||
|
|
@ -815,6 +815,68 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* %assign/ar <array>, <delay>, <bit>
|
||||||
|
* Generate an assignment event to a real array. Index register 3
|
||||||
|
* contains the canonical address of the word in the memory. <delay>
|
||||||
|
* is the delay in simulation time. <bit> is the index register
|
||||||
|
* containing the real value.
|
||||||
|
*/
|
||||||
|
bool of_ASSIGN_AR(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
long adr = thr->words[3].w_int;
|
||||||
|
unsigned delay = cp->bit_idx[0];
|
||||||
|
double value = thr->words[cp->bit_idx[1]].w_real;
|
||||||
|
|
||||||
|
if (adr >= 0) {
|
||||||
|
schedule_assign_array_word(cp->array, adr, value, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* %assign/ar/d <array>, <delay_idx>, <bit>
|
||||||
|
* Generate an assignment event to a real array. Index register 3
|
||||||
|
* contains the canonical address of the word in the memory.
|
||||||
|
* <delay_idx> is the integer register that contains the delay value.
|
||||||
|
* <bit> is the index register containing the real value.
|
||||||
|
*/
|
||||||
|
bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
long adr = thr->words[3].w_int;
|
||||||
|
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
|
||||||
|
double value = thr->words[cp->bit_idx[1]].w_real;
|
||||||
|
|
||||||
|
if (adr >= 0) {
|
||||||
|
schedule_assign_array_word(cp->array, adr, value, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* %assign/ar/e <array>, <bit>
|
||||||
|
* Generate an assignment event to a real array. Index register 3
|
||||||
|
* contains the canonical address of the word in the memory. <bit>
|
||||||
|
* is the index register containing the real value. The event
|
||||||
|
* information is contained in the thread event control registers
|
||||||
|
* and is set with %evctl.
|
||||||
|
*/
|
||||||
|
bool of_ASSIGN_ARE(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
long adr = thr->words[3].w_int;
|
||||||
|
double value = thr->words[cp->bit_idx[0]].w_real;
|
||||||
|
|
||||||
|
if (adr >= 0) {
|
||||||
|
if (thr->ecount == 0) {
|
||||||
|
schedule_assign_array_word(cp->array, adr, value, 0);
|
||||||
|
} else {
|
||||||
|
schedule_evctl(cp->array, adr, value, thr->event,
|
||||||
|
thr->ecount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* %assign/av <array>, <delay>, <bit>
|
/* %assign/av <array>, <delay>, <bit>
|
||||||
* This generates an assignment event to an array. Index register 0
|
* This generates an assignment event to an array. Index register 0
|
||||||
* contains the width of the vector (and the word) and index register
|
* contains the width of the vector (and the word) and index register
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue