Add force/release and assign/deassign for real values.

This patch adds assign/deassign for real variables and force/release
for real variables and nets.
This commit is contained in:
Cary R 2008-04-16 16:11:23 -07:00 committed by Stephen Williams
parent 23e60aa381
commit 6eb9825ab7
5 changed files with 182 additions and 10 deletions

View File

@ -801,6 +801,37 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope)
return 0;
}
static void force_real_to_lval(ivl_statement_t net, int res)
{
const char*command_name;
switch (ivl_statement_type(net)) {
case IVL_ST_CASSIGN:
command_name = "%cassign/wr";
break;
case IVL_ST_FORCE:
command_name = "%force/wr";
break;
default:
command_name = "ERROR";
assert(0);
break;
}
assert(ivl_stmt_lvals(net) == 1);
ivl_lval_t lval = ivl_stmt_lval(net, 0);
ivl_signal_t lsig = ivl_lval_sig(lval);
assert(ivl_lval_width(lval) == 1);
assert(ivl_lval_part_off(lval) == 0);
assert(ivl_lval_idx(lval) == 0);
/* L-Value must be a signal: reg or wire */
assert(lsig != 0);
fprintf(vvp_out, " %s v%p_0, %d;\n", command_name, lsig, res);
}
static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
{
unsigned lidx;
@ -936,16 +967,28 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
static int show_stmt_cassign(ivl_statement_t net)
{
ivl_expr_t rval;
struct vector_info rvec;
ivl_signal_t sig;
rval = ivl_stmt_rval(net);
assert(rval);
sig = ivl_lval_sig(ivl_stmt_lval(net, 0));
if (sig && ivl_signal_data_type(sig) == IVL_VT_REAL) {
int res;
res = draw_eval_real(ivl_stmt_rval(net));
clr_word(res);
force_real_to_lval(net, res);
} else {
struct vector_info rvec;
rvec = draw_eval_expr(rval, STUFF_OK_47);
/* Write out initial continuous assign instructions to assign
the expression value to the l-value. */
force_vector_to_lval(net, rvec);
}
force_link_rval(net, rval);
@ -959,6 +1002,18 @@ static int show_stmt_cassign(ivl_statement_t net)
*/
static int show_stmt_deassign(ivl_statement_t net)
{
ivl_signal_t sig = ivl_lval_sig(ivl_stmt_lval(net, 0));
if (sig && ivl_signal_data_type(sig) == IVL_VT_REAL) {
assert(ivl_stmt_lvals(net) == 1);
ivl_lval_t lval = ivl_stmt_lval(net, 0);
assert(ivl_lval_width(lval) == 1);
assert(ivl_lval_part_off(lval) == 0);
assert(ivl_lval_idx(lval) == 0);
fprintf(vvp_out, " %%deassign/wr v%p_0;\n", sig);
return 0;
}
unsigned lidx;
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
@ -1115,16 +1170,28 @@ static int show_stmt_disable(ivl_statement_t net, ivl_scope_t sscope)
static int show_stmt_force(ivl_statement_t net)
{
ivl_expr_t rval;
struct vector_info rvec;
ivl_signal_t sig;
rval = ivl_stmt_rval(net);
assert(rval);
sig = ivl_lval_sig(ivl_stmt_lval(net, 0));
if (sig && ivl_signal_data_type(sig) == IVL_VT_REAL) {
int res;
res = draw_eval_real(ivl_stmt_rval(net));
clr_word(res);
force_real_to_lval(net, res);
} else {
struct vector_info rvec;
rvec = draw_eval_expr(rval, STUFF_OK_47);
/* Write out initial continuous assign instructions to assign
the expression value to the l-value. */
force_vector_to_lval(net, rvec);
}
force_link_rval(net, rval);
@ -1213,6 +1280,22 @@ static int show_stmt_noop(ivl_statement_t net)
static int show_stmt_release(ivl_statement_t net)
{
ivl_signal_t sig = ivl_lval_sig(ivl_stmt_lval(net, 0));
if (sig && ivl_signal_data_type(sig) == IVL_VT_REAL) {
unsigned type = 0;
assert(ivl_stmt_lvals(net) == 1);
ivl_lval_t lval = ivl_stmt_lval(net, 0);
assert(ivl_lval_width(lval) == 1);
assert(ivl_lval_part_off(lval) == 0);
assert(ivl_lval_idx(lval) == 0);
if (ivl_signal_type(sig) == IVL_SIT_REG) type = 1;
fprintf(vvp_out, " %%release/wr v%p_0, %u;\n", sig, type);
return 0;
}
unsigned lidx;
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {

View File

@ -52,6 +52,7 @@ extern bool of_BLEND_WR(vthread_t thr, vvp_code_t code);
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_WR(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_X0(vthread_t thr, vvp_code_t code);
extern bool of_CMPIS(vthread_t thr, vvp_code_t code);
extern bool of_CMPIU(vthread_t thr, vvp_code_t code);
@ -66,6 +67,7 @@ extern bool of_CVT_IR(vthread_t thr, vvp_code_t code);
extern bool of_CVT_RI(vthread_t thr, vvp_code_t code);
extern bool of_CVT_VR(vthread_t thr, vvp_code_t code);
extern bool of_DEASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_DEASSIGN_WR(vthread_t thr, vvp_code_t code);
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
extern bool of_DELAYX(vthread_t thr, vvp_code_t code);
extern bool of_DISABLE(vthread_t thr, vvp_code_t code);
@ -75,6 +77,7 @@ extern bool of_DIV_WR(vthread_t thr, vvp_code_t code);
extern bool of_END(vthread_t thr, vvp_code_t code);
extern bool of_FORCE_LINK(vthread_t thr, vvp_code_t code);
extern bool of_FORCE_V(vthread_t thr, vvp_code_t code);
extern bool of_FORCE_WR(vthread_t thr, vvp_code_t code);
extern bool of_FORCE_X0(vthread_t thr, vvp_code_t code);
extern bool of_FORK(vthread_t thr, vvp_code_t code);
extern bool of_INV(vthread_t thr, vvp_code_t code);
@ -121,6 +124,7 @@ extern bool of_POW(vthread_t thr, vvp_code_t code);
extern bool of_POW_WR(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
extern bool of_SET_MV(vthread_t thr, vvp_code_t code);
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);

View File

@ -101,6 +101,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cassign/link",of_CASSIGN_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
{ "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%cassign/wr",of_CASSIGN_WR,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
{ "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@ -115,6 +116,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@ -123,6 +125,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%end", of_END, 0, {OA_NONE, OA_NONE, 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/x0",of_FORCE_X0,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%ix/add", of_IX_ADD, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
@ -168,6 +171,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%pow/wr", of_POW_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%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} },
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
{ "%set/mv", of_SET_MV, 3, {OA_MEM_PTR, OA_BIT1, OA_BIT2} },
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },

View File

@ -168,6 +168,11 @@ variable. This is similar to %set, but it uses the cassign port
signal responds differently. See "VARIABLE STATEMENTS" in the
README.txt file.
* %cassign/wr <var-label>, <bit>
Perform a continuous assign of a constant real value to the target
variable. See %cassign/v above.
* %cassign/x0 <label>, <bit>, <wid>
Perform continuous assign of a constant value to part of the target
@ -255,6 +260,10 @@ The <base> and <width> are used to determine what part of the signal
will be deactivated. For a full deactivation the <base> is 0 and
<width> is the entire signal width.
* %deassign/wr <var-label>
The same as %deassign above except this is used for real variables.
* %delay <delay>
This opcode pauses the thread, and causes it to be rescheduled for a
@ -300,6 +309,10 @@ functor instead of the normal assign port (port-0), so the signal
responds differently. See "VARIABLE STATEMENTS" and "NET STATEMENTS"
in the README.txt file.
* %force/wr <var-label>, <bit>
Force a constant real value to the target variable. See %force/v above.
* %force/x0 <label>, <bit>, <wid>
Force a constant value to part of the target variable. This is similar
@ -619,6 +632,13 @@ The <base> and <width> are used to determine what part of the signal
will be released. For a full release the <base> is 0 and <width> is
the entire signal width.
* %release/wr <functor-label>, <type>
Release the force on the real signal that is represented by the functor
<functor-label>. The force was previously activated with a %force/wr
statement. The <type> is 0 for nets and 1 for registers. See the other
%release commands above.
* %set/v <var-label>, <bit>, <wid>
This sets a vector to a variable, and is used to implement blocking

View File

@ -845,6 +845,18 @@ bool of_CASSIGN_V(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_CASSIGN_WR(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
double value = thr->words[cp->bit_idx[0]].w_real;
/* Set the value into port 1 of the destination. */
vvp_net_ptr_t ptr (net, 1);
vvp_send_real(ptr, value);
return true;
}
bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
@ -1241,6 +1253,20 @@ bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_DEASSIGN_WR(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
vvp_fun_signal_real*sig = reinterpret_cast<vvp_fun_signal_real*>(net->fun);
assert(sig);
vvp_net_ptr_t ptr (net, 3);
vvp_send_long(ptr, 1);
return true;
}
/*
* The delay takes two 32bit numbers to make up a 64bit time.
*
@ -1833,6 +1859,19 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_FORCE_WR(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
double value = thr->words[cp->bit_idx[0]].w_real;
/* Set the value into port 2 of the destination. */
vvp_net_ptr_t ptr (net, 2);
vvp_send_real(ptr, value);
return true;
}
bool of_FORCE_X0(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
@ -3380,6 +3419,28 @@ bool of_RELEASE_REG(vthread_t thr, vvp_code_t cp)
return true;
}
/* The type is 1 for registers and 0 for everything else. */
bool of_RELEASE_WR(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
unsigned type = cp->bit_idx[0];
vvp_fun_signal_real*sig = reinterpret_cast<vvp_fun_signal_real*>(net->fun);
assert(sig);
// This is the net that is forcing me...
if (vvp_net_t*src = sig->force_link) {
// And this is the pointer to be removed.
vvp_net_ptr_t dst_ptr (net, 2);
unlink_from_driver(src, dst_ptr);
}
// Send a command to this signal to unforce itself.
vvp_net_ptr_t ptr (net, 3);
vvp_send_long(ptr, 2 + type);
return true;
}
/*
* This implements the "%set/av <label>, <bit>, <wid>" instruction. In