Merge branch 'master' of ssh://steve-icarus@icarus.com/home/u/icarus/steve/git/verilog
This commit is contained in:
commit
e1bf2ec019
|
|
@ -1217,6 +1217,7 @@ void Design::dump(ostream&o) const
|
|||
if (nodes_) {
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
do {
|
||||
assert(cur);
|
||||
cur->dump_node(o, 0);
|
||||
cur = cur->node_next_;
|
||||
} while (cur != nodes_->node_next_);
|
||||
|
|
|
|||
96
elab_net.cc
96
elab_net.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
|
|
@ -500,16 +500,24 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned operand_width;
|
||||
bool real_arg = false;
|
||||
if (lexp->expr_type() == IVL_VT_REAL ||
|
||||
rexp->expr_type() == IVL_VT_REAL) {
|
||||
operand_width = 1;
|
||||
real_arg = true;
|
||||
} else {
|
||||
/* Choose the operand width to be the width of the widest
|
||||
self-determined operand. */
|
||||
unsigned operand_width = lexp->expr_width();
|
||||
if (rexp->expr_width() > operand_width)
|
||||
operand_width = rexp->expr_width();
|
||||
operand_width = lexp->expr_width();
|
||||
if (rexp->expr_width() > operand_width)
|
||||
operand_width = rexp->expr_width();
|
||||
|
||||
lexp->set_width(operand_width);
|
||||
lexp = pad_to_width(lexp, operand_width);
|
||||
rexp->set_width(operand_width);
|
||||
rexp = pad_to_width(rexp, operand_width);
|
||||
lexp->set_width(operand_width);
|
||||
lexp = pad_to_width(lexp, operand_width);
|
||||
rexp->set_width(operand_width);
|
||||
rexp = pad_to_width(rexp, operand_width);
|
||||
}
|
||||
|
||||
NetNet*lsig = 0;
|
||||
NetNet*rsig = 0;
|
||||
|
|
@ -530,12 +538,19 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
delete lexp;
|
||||
lexp = 0;
|
||||
|
||||
NetNet*osig = compare_eq_constant(des, scope,
|
||||
lsig, tmp, op_,
|
||||
rise, fall, decay);
|
||||
if (osig != 0) {
|
||||
if (real_arg) {
|
||||
verireal vrl(tmp->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
rsig = rlval.synthesize(des);
|
||||
delete rexp;
|
||||
return osig;
|
||||
} else {
|
||||
NetNet*osig = compare_eq_constant(des, scope,
|
||||
lsig, tmp, op_,
|
||||
rise, fall, decay);
|
||||
if (osig != 0) {
|
||||
delete rexp;
|
||||
return osig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -545,12 +560,19 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
assert(rsig);
|
||||
delete rexp;
|
||||
|
||||
NetNet*osig = compare_eq_constant(des, scope,
|
||||
rsig, tmp, op_,
|
||||
rise, fall, decay);
|
||||
if (osig != 0) {
|
||||
if (real_arg) {
|
||||
verireal vrl(tmp->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
lsig = rlval.synthesize(des);
|
||||
delete lexp;
|
||||
return osig;
|
||||
} else {
|
||||
NetNet*osig = compare_eq_constant(des, scope,
|
||||
rsig, tmp, op_,
|
||||
rise, fall, decay);
|
||||
if (osig != 0) {
|
||||
delete lexp;
|
||||
return osig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -572,11 +594,18 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
/* Operands of binary compare need to be padded to equal
|
||||
size. Figure the pad bit needed to extend the narrowest
|
||||
vector. */
|
||||
if (lsig->vector_width() < dwidth)
|
||||
if (!real_arg && lsig->vector_width() < dwidth)
|
||||
lsig = pad_to_width(des, lsig, dwidth);
|
||||
if (rsig->vector_width() < dwidth)
|
||||
if (!real_arg && rsig->vector_width() < dwidth)
|
||||
rsig = pad_to_width(des, rsig, dwidth);
|
||||
|
||||
/* For now the runtime cannot convert a vec4 to a real value. */
|
||||
if (real_arg && (rsig->data_type() != IVL_VT_REAL ||
|
||||
lsig->data_type() != IVL_VT_REAL)) {
|
||||
cerr << get_fileline() << ": sorry: comparing bit based signals "
|
||||
"and real values is not supported." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
|
|
@ -619,6 +648,11 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
case 'E': // Case equals (===)
|
||||
if (real_arg) {
|
||||
cerr << get_fileline() << ": error: Case equality may not "
|
||||
"have real operands." << endl;
|
||||
return 0;
|
||||
}
|
||||
gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, true);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
|
|
@ -626,6 +660,11 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
break;
|
||||
|
||||
case 'N': // Case equals (!==)
|
||||
if (real_arg) {
|
||||
cerr << get_fileline() << ": error: Case inequality may not "
|
||||
"have real operands." << endl;
|
||||
return 0;
|
||||
}
|
||||
gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, false);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
|
|
@ -636,7 +675,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
|
||||
/* Handle the special case of single bit compare with a
|
||||
single XNOR gate. This is easy and direct. */
|
||||
if (dwidth == 1) {
|
||||
if (dwidth == 1 && !real_arg){
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XNOR, 1);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
|
|
@ -664,7 +703,8 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
|
||||
/* Handle the special case of single bit compare with a
|
||||
single XOR gate. This is easy and direct. */
|
||||
if (dwidth == 1) {
|
||||
if (dwidth == 1 && lsig->data_type() != IVL_VT_REAL &&
|
||||
rsig->data_type() != IVL_VT_REAL) {
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR, 1);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
|
|
@ -1124,7 +1164,7 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
|
|||
connect(cc->pin(0), osig->pin(0));
|
||||
|
||||
/* Make the part select of the left expression and
|
||||
connect it to the lsb or msb of the concatenation,
|
||||
connect it to the LSB or MSB of the concatenation,
|
||||
depending on the direction of the shift. */
|
||||
NetPartSelect*part;
|
||||
|
||||
|
|
@ -1439,7 +1479,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
|||
delete etmp;
|
||||
|
||||
if (repeat == 0) {
|
||||
cerr << get_fileline() << ": error: Concatenation epeat "
|
||||
cerr << get_fileline() << ": error: Concatenation repeat "
|
||||
"may not be 0."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
|
|
@ -1448,7 +1488,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() <<": debug: PEConcat concat repeat="
|
||||
cerr << get_fileline() <<": debug: PEConcat concatenation repeat="
|
||||
<< repeat << "." << endl;
|
||||
}
|
||||
|
||||
|
|
@ -1861,7 +1901,7 @@ NetNet* PEIdent::elaborate_net_net_idx_up_(Design*des, NetScope*scope,
|
|||
// convert from -: to +: form.
|
||||
if (down_flag) lsv -= (wid-1);
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// If the part select covers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (sig->sb_to_idx(lsv) == 0 && wid == sig->vector_width())
|
||||
|
|
@ -2576,7 +2616,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
|||
return 0;
|
||||
|
||||
/* This should not happen. A PWire can only become
|
||||
PIMPLICIT if this is a udp reg port, and the make_udp
|
||||
PIMPLICIT if this is a UDP reg port, and the make_udp
|
||||
function should turn it into an output.... I think. */
|
||||
|
||||
case NetNet::PIMPLICIT:
|
||||
|
|
@ -2795,7 +2835,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
if (tru_sig->data_type() != fal_sig->data_type()) {
|
||||
cerr << get_fileline() << ": error: True and False clauses of"
|
||||
<< " ternary expression have differnt types." << endl;
|
||||
<< " ternary expression have different types." << endl;
|
||||
cerr << get_fileline() << ": : True clause is "
|
||||
<< tru_sig->data_type() << ", false clause is "
|
||||
<< fal_sig->data_type() << "." << endl;
|
||||
|
|
|
|||
|
|
@ -1132,6 +1132,9 @@ NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
|
|||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Address"), 0);
|
||||
// Increment the expression reference count for the target
|
||||
// memory so that it is not deleted underneath me.
|
||||
mem->incr_eref();
|
||||
}
|
||||
|
||||
NetArrayDq::~NetArrayDq()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2005-2008 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
|
||||
|
|
@ -33,8 +33,10 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp)
|
|||
assert(ivl_signal_array_count(port) == 1);
|
||||
|
||||
res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0);
|
||||
assert(res.wid <= ivl_signal_width(port));
|
||||
fprintf(vvp_out, " %%set/v v%p_0, %u, %u;\n", port, res.base, res.wid);
|
||||
/* We could have extra bits so only select the ones we need. */
|
||||
unsigned pwidth = ivl_signal_width(port);
|
||||
fprintf(vvp_out, " %%set/v v%p_0, %u, %u;\n", port, res.base,
|
||||
(res.wid > pwidth) ? pwidth : res.wid);
|
||||
|
||||
clr_vector(res);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,12 +128,12 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%ix/load %u, %u;\n", ix, value);
|
||||
fprintf(vvp_out, " %%ix/load %u, %u;\n", ix, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_EX_ULONG:
|
||||
fprintf(vvp_out, " %%ix/load %u, %lu;\n", ix, ivl_expr_uvalue(expr));
|
||||
fprintf(vvp_out, " %%ix/load %u, %lu;\n", ix, ivl_expr_uvalue(expr));
|
||||
break;
|
||||
|
||||
case IVL_EX_SIGNAL: {
|
||||
|
|
@ -141,17 +141,25 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
|||
unsigned word = 0;
|
||||
if (ivl_signal_array_count(sig) > 1) {
|
||||
ivl_expr_t ixe = ivl_expr_oper1(expr);
|
||||
assert(number_is_immediate(ixe, 8*sizeof(unsigned long)));
|
||||
word = get_number_immediate(ixe);
|
||||
if (number_is_immediate(ixe, 8*sizeof(unsigned long)))
|
||||
word = get_number_immediate(ixe);
|
||||
else {
|
||||
struct vector_info rv;
|
||||
rv = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, rv.base, rv.wid);
|
||||
clr_vector(rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(vvp_out, " %%ix/getv %u, v%p_%u;\n", ix, sig, word);
|
||||
fprintf(vvp_out, " %%ix/getv %u, v%p_%u;\n", ix, sig, word);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
struct vector_info rv;
|
||||
rv = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, rv.base, rv.wid);
|
||||
clr_vector(rv);
|
||||
break;
|
||||
|
|
@ -1771,7 +1779,7 @@ 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. */
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate);
|
||||
fprintf(vvp_out, " %%ix/load 2, %lu;\n", res.wid);
|
||||
fprintf(vvp_out, " %%ix/load 2, %u;\n", res.wid);
|
||||
fprintf(vvp_out, " %%load/vp0 %u, v%p_%u, %u;\n",
|
||||
res.base, sig, word, swid);
|
||||
swid = res.wid;
|
||||
|
|
|
|||
|
|
@ -236,14 +236,28 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
|
||||
if (part_off_ex) {
|
||||
unsigned skip_assign = transient_id++;
|
||||
assert(dexp == 0);
|
||||
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, "t_%u ;\n", skip_assign);
|
||||
if (dexp == 0) {
|
||||
/* Constant delay... */
|
||||
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, "t_%u ;\n", skip_assign);
|
||||
} else {
|
||||
/* Calculated delay... */
|
||||
int delay_index = allocate_word();
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
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_index, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
clr_word(delay_index);
|
||||
}
|
||||
|
||||
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
|
||||
/* There is no mux expression, but a constant part
|
||||
|
|
|
|||
|
|
@ -1606,7 +1606,7 @@ static void draw_lpm_add(ivl_lpm_t net)
|
|||
ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
|
||||
ivl_variable_type_t dto = IVL_VT_LOGIC;
|
||||
|
||||
if (dta == IVL_VT_REAL && dtb == IVL_VT_REAL)
|
||||
if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL)
|
||||
dto = IVL_VT_REAL;
|
||||
|
||||
width = ivl_lpm_width(net);
|
||||
|
|
@ -1676,29 +1676,51 @@ static void draw_lpm_cmp(ivl_lpm_t net)
|
|||
unsigned width;
|
||||
const char*type = "";
|
||||
const char*signed_string = ivl_lpm_signed(net)? ".s" : "";
|
||||
ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0));
|
||||
ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
|
||||
ivl_variable_type_t dtc = IVL_VT_LOGIC;
|
||||
|
||||
if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL)
|
||||
dtc = IVL_VT_REAL;
|
||||
|
||||
width = ivl_lpm_width(net);
|
||||
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
assert(dtc != IVL_VT_REAL); /* Should never get here! */
|
||||
type = "eeq";
|
||||
signed_string = "";
|
||||
break;
|
||||
case IVL_LPM_CMP_EQ:
|
||||
type = "eq";
|
||||
if (dtc == IVL_VT_REAL)
|
||||
type = "eq.r";
|
||||
else
|
||||
type = "eq";
|
||||
signed_string = "";
|
||||
break;
|
||||
case IVL_LPM_CMP_GE:
|
||||
type = "ge";
|
||||
if (dtc == IVL_VT_REAL) {
|
||||
type = "ge.r";
|
||||
signed_string = "";
|
||||
} else
|
||||
type = "ge";
|
||||
break;
|
||||
case IVL_LPM_CMP_GT:
|
||||
type = "gt";
|
||||
if (dtc == IVL_VT_REAL) {
|
||||
type = "gt.r";
|
||||
signed_string = "";
|
||||
} else
|
||||
type = "gt";
|
||||
break;
|
||||
case IVL_LPM_CMP_NE:
|
||||
type = "ne";
|
||||
if (dtc == IVL_VT_REAL)
|
||||
type = "ne.r";
|
||||
else
|
||||
type = "ne";
|
||||
signed_string = "";
|
||||
break;
|
||||
case IVL_LPM_CMP_NEE:
|
||||
assert(dtc != IVL_VT_REAL); /* Should never get here! */
|
||||
type = "nee";
|
||||
signed_string = "";
|
||||
break;
|
||||
|
|
|
|||
132
verinum.cc
132
verinum.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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
|
||||
|
|
@ -16,15 +16,15 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: verinum.cc,v 1.52 2007/02/25 23:08:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "verinum.h"
|
||||
# include <iostream>
|
||||
# include <cassert>
|
||||
# include <math.h> // Needed to get pow for as_double().
|
||||
|
||||
static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c);
|
||||
|
||||
verinum::verinum()
|
||||
: bits_(0), nbits_(0), has_len_(false), has_sign_(false), string_flag_(false)
|
||||
|
|
@ -332,6 +332,35 @@ signed long verinum::as_long() const
|
|||
return val;
|
||||
}
|
||||
|
||||
double verinum::as_double() const
|
||||
{
|
||||
if (nbits_ == 0) return 0.0;
|
||||
|
||||
/* Do we have a signed value? */
|
||||
bool signed_flag = false;
|
||||
if (bits_[nbits_-1] == V1) {
|
||||
signed_flag = true;
|
||||
}
|
||||
|
||||
double val = 0.0;
|
||||
if (signed_flag) {
|
||||
V carry = V1;
|
||||
for (unsigned idx = 0; idx < nbits_; idx += 1) {
|
||||
V sum = add_with_carry(~bits_[idx], V0, carry);
|
||||
if (sum == V1)
|
||||
val += pow(2.0, (double)idx);
|
||||
}
|
||||
val *= -1.0;
|
||||
// val = (double) as_long();
|
||||
} else {
|
||||
for (unsigned idx = 0; idx < nbits_; idx += 1) {
|
||||
if (bits_[idx] == V1)
|
||||
val += pow(2.0, (double)idx);
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
string verinum::as_string() const
|
||||
{
|
||||
assert( nbits_%8 == 0 );
|
||||
|
|
@ -1158,98 +1187,3 @@ verinum::V operator ^ (verinum::V l, verinum::V r)
|
|||
return verinum::Vx;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: verinum.cc,v $
|
||||
* Revision 1.52 2007/02/25 23:08:24 steve
|
||||
* Process Verilog escape sequences much earlier.
|
||||
*
|
||||
* Revision 1.51 2007/01/27 05:36:11 steve
|
||||
* Fix padding of x when literal is sized and unsigned.
|
||||
*
|
||||
* Revision 1.50 2007/01/19 05:42:04 steve
|
||||
* Fix calculation of verinum pow operation.
|
||||
*
|
||||
* Revision 1.49 2006/12/08 19:56:09 steve
|
||||
* Handle very wide signed divide.
|
||||
*
|
||||
* Revision 1.48 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.47 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.46 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.45 2006/06/01 03:54:51 steve
|
||||
* Fix broken subtraction of small constants.
|
||||
*
|
||||
* Revision 1.44 2005/12/07 04:04:24 steve
|
||||
* Allow constant concat expressions.
|
||||
*
|
||||
* Revision 1.43 2004/05/18 18:43:15 steve
|
||||
* Handle null string as a single nul character.
|
||||
*
|
||||
* Revision 1.42 2004/02/17 06:52:55 steve
|
||||
* Support unsigned divide of huge numbers.
|
||||
*
|
||||
* Revision 1.41 2003/10/26 04:54:56 steve
|
||||
* Support constant evaluation of binary ^ operator.
|
||||
*
|
||||
* Revision 1.40 2003/05/25 03:01:19 steve
|
||||
* Get length of trimed unsigned value right.
|
||||
*
|
||||
* Revision 1.39 2003/04/14 03:40:21 steve
|
||||
* Make some effort to preserve bits while
|
||||
* operating on constant values.
|
||||
*
|
||||
* Revision 1.38 2003/04/03 04:30:00 steve
|
||||
* Prevent overrun comparing verinums to zero.
|
||||
*
|
||||
* Revision 1.37 2003/02/02 00:43:16 steve
|
||||
* Fix conversion of signed numbes to long
|
||||
*
|
||||
* Revision 1.36 2003/01/30 16:23:08 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.35 2002/08/19 02:39:17 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
* Revision 1.34 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.33 2002/04/27 23:26:24 steve
|
||||
* Trim leading nulls from string forms.
|
||||
*
|
||||
* Revision 1.32 2002/04/27 04:48:43 steve
|
||||
* Display string verinums as strings.
|
||||
*
|
||||
* Revision 1.31 2002/02/01 05:09:14 steve
|
||||
* Propagate sign in unary minus.
|
||||
*
|
||||
* Revision 1.30 2001/12/31 00:02:33 steve
|
||||
* Include s indicator in dump of signed numbers.
|
||||
*
|
||||
* Revision 1.29 2001/11/19 02:54:12 steve
|
||||
* Handle division and modulus by zero while
|
||||
* evaluating run-time constants.
|
||||
*
|
||||
* Revision 1.28 2001/11/06 06:11:55 steve
|
||||
* Support more real arithmetic in delay constants.
|
||||
*
|
||||
* Revision 1.27 2001/07/25 03:10:50 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.26 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.25 2001/02/08 05:38:18 steve
|
||||
* trim the length of unsized numbers.
|
||||
*
|
||||
* Revision 1.24 2001/02/07 21:47:13 steve
|
||||
* Fix expression widths for rvalues and parameters (PR#131,132)
|
||||
*/
|
||||
|
||||
|
|
|
|||
117
verinum.h
117
verinum.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __verinum_H
|
||||
#define __verinum_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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
|
||||
|
|
@ -18,9 +18,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: verinum.h,v 1.33 2007/02/02 04:33:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
||||
|
|
@ -93,6 +90,7 @@ class verinum {
|
|||
uint64_t as_ulong64() const;
|
||||
unsigned long as_ulong() const;
|
||||
signed long as_long() const;
|
||||
double as_double() const;
|
||||
string as_string() const;
|
||||
|
||||
private:
|
||||
|
|
@ -158,115 +156,4 @@ extern verinum concat(const verinum&left, const verinum&right);
|
|||
/* Bitwise not returns the ones complement. */
|
||||
extern verinum v_not(const verinum&left);
|
||||
|
||||
/*
|
||||
* $Log: verinum.h,v $
|
||||
* Revision 1.33 2007/02/02 04:33:01 steve
|
||||
* Use inttypes.h instead of stdint.h for portability.
|
||||
*
|
||||
* Revision 1.32 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.31 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.30 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.29 2006/06/01 03:54:51 steve
|
||||
* Fix broken subtraction of small constants.
|
||||
*
|
||||
* Revision 1.28 2005/12/07 04:04:24 steve
|
||||
* Allow constant concat expressions.
|
||||
*
|
||||
* Revision 1.27 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
*
|
||||
* Revision 1.26 2004/02/17 06:52:55 steve
|
||||
* Support unsigned divide of huge numbers.
|
||||
*
|
||||
* Revision 1.25 2003/10/26 04:54:56 steve
|
||||
* Support constant evaluation of binary ^ operator.
|
||||
*
|
||||
* Revision 1.24 2003/04/14 03:40:21 steve
|
||||
* Make some effort to preserve bits while
|
||||
* operating on constant values.
|
||||
*
|
||||
* Revision 1.23 2003/04/03 04:30:00 steve
|
||||
* Prevent overrun comparing verinums to zero.
|
||||
*
|
||||
* Revision 1.22 2003/01/30 16:23:08 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.21 2003/01/30 04:23:25 steve
|
||||
* include config.h to get iosfwd flags.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.19 2002/06/03 04:04:24 steve
|
||||
* Add verinum != operator.
|
||||
*
|
||||
* Revision 1.18 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.17 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.16 2001/02/07 02:46:31 steve
|
||||
* Support constant evaluation of / and % (PR#124)
|
||||
*
|
||||
* Revision 1.15 2001/01/16 02:44:18 steve
|
||||
* Use the iosfwd header if available.
|
||||
*
|
||||
* Revision 1.14 2001/01/02 03:23:40 steve
|
||||
* Evaluate constant &, | and unary ~.
|
||||
*
|
||||
* Revision 1.13 2000/12/10 22:01:36 steve
|
||||
* Support decimal constants in behavioral delays.
|
||||
*
|
||||
* Revision 1.12 2000/09/27 18:28:37 steve
|
||||
* multiply in parameter expressions.
|
||||
*
|
||||
* Revision 1.11 2000/02/23 04:43:43 steve
|
||||
* Some compilers do not accept the not symbol.
|
||||
*
|
||||
* Revision 1.10 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/07 03:45:49 steve
|
||||
* Initial support for signed constants.
|
||||
*
|
||||
* Revision 1.8 1999/11/06 16:00:17 steve
|
||||
* Put number constants into a static table.
|
||||
*
|
||||
* Revision 1.7 1999/10/22 23:57:53 steve
|
||||
* do the <= in bits, not numbers.
|
||||
*
|
||||
* Revision 1.6 1999/10/10 23:29:37 steve
|
||||
* Support evaluating + operator at compile time.
|
||||
*
|
||||
* Revision 1.5 1999/05/13 04:02:09 steve
|
||||
* More precise handling of verinum bit lengths.
|
||||
*
|
||||
* Revision 1.4 1998/12/20 02:05:41 steve
|
||||
* Function to calculate wire initial value.
|
||||
*
|
||||
* Revision 1.3 1998/11/11 00:01:51 steve
|
||||
* Check net ranges in declarations.
|
||||
*
|
||||
* Revision 1.2 1998/11/09 18:55:35 steve
|
||||
* Add procedural while loops,
|
||||
* Parse procedural for loops,
|
||||
* Add procedural wait statements,
|
||||
* Add constant nodes,
|
||||
* Add XNOR logic gate,
|
||||
* Make vvm output look a bit prettier.
|
||||
*
|
||||
* Revision 1.1 1998/11/03 23:29:08 steve
|
||||
* Introduce verilog to CVS.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
|
|||
64
vvp/arith.cc
64
vvp/arith.cc
|
|
@ -821,3 +821,67 @@ void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
|||
vvp_send_real(ptr.ptr()->out, val);
|
||||
}
|
||||
|
||||
/* Real compare equal. */
|
||||
vvp_cmp_eq_real::vvp_cmp_eq_real()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
vvp_vector4_t res (1);
|
||||
if (op_a_ == op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
}
|
||||
|
||||
/* Real compare not equal. */
|
||||
vvp_cmp_ne_real::vvp_cmp_ne_real()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
vvp_vector4_t res (1);
|
||||
if (op_a_ != op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
}
|
||||
|
||||
/* Real compare greater than or equal. */
|
||||
vvp_cmp_ge_real::vvp_cmp_ge_real()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
vvp_vector4_t res (1);
|
||||
if (op_a_ >= op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
}
|
||||
|
||||
/* Real compare greater than. */
|
||||
vvp_cmp_gt_real::vvp_cmp_gt_real()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
vvp_vector4_t res (1);
|
||||
if (op_a_ > op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
}
|
||||
|
||||
|
|
|
|||
28
vvp/arith.h
28
vvp/arith.h
|
|
@ -247,4 +247,32 @@ class vvp_arith_sub_real : public vvp_arith_real_ {
|
|||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
};
|
||||
|
||||
class vvp_cmp_eq_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_eq_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
};
|
||||
|
||||
class vvp_cmp_ne_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_ne_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
};
|
||||
|
||||
class vvp_cmp_ge_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_ge_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
};
|
||||
|
||||
class vvp_cmp_gt_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_gt_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1052,6 +1052,18 @@ void compile_cmp_eq(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void compile_cmp_ne(char*label, long wid, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
assert( wid > 0 );
|
||||
|
|
@ -1066,6 +1078,18 @@ void compile_cmp_ne(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void compile_cmp_ge(char*label, long wid, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
|
|
@ -1082,6 +1106,18 @@ void compile_cmp_ge(char*label, long wid, bool signed_flag,
|
|||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void compile_cmp_gt(char*label, long wid, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
|
|
@ -1098,6 +1134,18 @@ void compile_cmp_gt(char*label, long wid, bool signed_flag,
|
|||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void compile_delay(char*label, vvp_delay_t*delay, struct symb_s arg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -174,6 +174,10 @@ extern void compile_arith_mult_r(char*label, unsigned argc,
|
|||
extern void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_sum_r(char*label, unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_sub_r(char*label, unsigned argc, struct symb_s*argv);
|
||||
extern void compile_cmp_eq_r(char*label, unsigned argc, struct symb_s*argv);
|
||||
extern void compile_cmp_ne_r(char*label, unsigned argc, struct symb_s*argv);
|
||||
extern void compile_cmp_ge_r(char*label, unsigned argc, struct symb_s*argv);
|
||||
extern void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_dff(char*label,
|
||||
struct symb_s arg_d,
|
||||
|
|
|
|||
|
|
@ -104,11 +104,15 @@
|
|||
".array/port" { return K_ARRAY_PORT; }
|
||||
".cmp/eeq" { return K_CMP_EEQ; }
|
||||
".cmp/eq" { return K_CMP_EQ; }
|
||||
".cmp/eq.r" { return K_CMP_EQ_R; }
|
||||
".cmp/nee" { return K_CMP_NEE; }
|
||||
".cmp/ne" { return K_CMP_NE; }
|
||||
".cmp/ne.r" { return K_CMP_NE_R; }
|
||||
".cmp/ge" { return K_CMP_GE; }
|
||||
".cmp/ge.r" { return K_CMP_GE_R; }
|
||||
".cmp/ge.s" { return K_CMP_GE_S; }
|
||||
".cmp/gt" { return K_CMP_GT; }
|
||||
".cmp/gt.r" { return K_CMP_GT_R; }
|
||||
".cmp/gt.s" { return K_CMP_GT_S; }
|
||||
".concat" { return K_CONCAT; }
|
||||
".delay" { return K_DELAY; }
|
||||
|
|
|
|||
25
vvp/parse.y
25
vvp/parse.y
|
|
@ -69,8 +69,8 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT
|
||||
%token K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R K_ARITH_SUM K_ARITH_SUM_R
|
||||
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
|
||||
%token K_CMP_EEQ K_CMP_EQ K_CMP_NEE K_CMP_NE
|
||||
%token K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S
|
||||
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
|
||||
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
|
||||
%token K_CONCAT K_DEBUG K_DELAY K_DFF
|
||||
%token K_EVENT K_EVENT_OR K_EXTEND_S K_FUNCTOR K_MODPATH K_NET K_NET_S K_NET_R
|
||||
%token K_NET8 K_NET8_S
|
||||
|
|
@ -315,16 +315,31 @@ statement
|
|||
compile_cmp_eq($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_EQ_R T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_eq_r($1, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_NE T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_ne($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_NE_R T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_ne_r($1, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_GE T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_ge($1, $3, false, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_GE_R T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_ge_r($1, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_GE_S T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_ge($1, $3, true, obj.cnt, obj.vect);
|
||||
|
|
@ -334,6 +349,12 @@ statement
|
|||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_gt($1, $3, false, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_GT_R T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_gt_r($1, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_GT_S T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_gt($1, $3, true, obj.cnt, obj.vect);
|
||||
|
|
|
|||
Loading…
Reference in New Issue