Compare commits
20 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
4205752bb0 | |
|
|
d237e35076 | |
|
|
90f37fe3cb | |
|
|
4be2f61b53 | |
|
|
f8aa9073ac | |
|
|
9ea20d6677 | |
|
|
9fec1f7e45 | |
|
|
c47ea0721c | |
|
|
ef12137931 | |
|
|
0e8a12eebf | |
|
|
9473e823ed | |
|
|
c75f9db315 | |
|
|
1d31a91b4f | |
|
|
b795d8c1d8 | |
|
|
5ec7731e04 | |
|
|
bb29e1d588 | |
|
|
74fd1865cb | |
|
|
b40b6fb50d | |
|
|
19b68f6332 | |
|
|
c96e4da9e4 |
|
|
@ -2,7 +2,6 @@
|
||||||
CADENCE PLI1 MODULES
|
CADENCE PLI1 MODULES
|
||||||
|
|
||||||
Copyright 2003 Stephen Williams
|
Copyright 2003 Stephen Williams
|
||||||
$Id: cadpli.txt,v 1.2 2003/02/17 00:01:25 steve Exp $
|
|
||||||
|
|
||||||
With the cadpli module, Icarus Verilog is able to load PLI1
|
With the cadpli module, Icarus Verilog is able to load PLI1
|
||||||
applications that were compiled and linked to be dynamic loaded by
|
applications that were compiled and linked to be dynamic loaded by
|
||||||
|
|
@ -34,15 +33,3 @@ the +loadpli1= argument to Verilog-XL.
|
||||||
The integration from this point is seamless. The PLI application
|
The integration from this point is seamless. The PLI application
|
||||||
hardly knows that it is being invoked by Icarus Verilog instead of
|
hardly knows that it is being invoked by Icarus Verilog instead of
|
||||||
Verilog-XL, so operates as it would otherwise.
|
Verilog-XL, so operates as it would otherwise.
|
||||||
|
|
||||||
$Log: cadpli.txt,v $
|
|
||||||
Revision 1.2 2003/02/17 00:01:25 steve
|
|
||||||
Use a variant of ivl_dlfcn to do dynamic loading
|
|
||||||
from within the cadpli module.
|
|
||||||
|
|
||||||
Change the +cadpli flag to -cadpli, to keep the
|
|
||||||
plusargs namespace clear.
|
|
||||||
|
|
||||||
Revision 1.1 2003/02/16 02:44:47 steve
|
|
||||||
Add the cadpli HOWTO.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,12 @@ extern bool debug_elab_pexpr;
|
||||||
extern bool debug_synth2;
|
extern bool debug_synth2;
|
||||||
extern bool debug_optimizer;
|
extern bool debug_optimizer;
|
||||||
|
|
||||||
|
/* Possibly temporary flag to control virtualization of pin arrays */
|
||||||
|
extern bool disable_virtual_pins;
|
||||||
|
|
||||||
|
/* Limit to size of devirtualized arrays */
|
||||||
|
extern unsigned long array_size_limit;
|
||||||
|
|
||||||
/* Path to a directory useful for finding subcomponents. */
|
/* Path to a directory useful for finding subcomponents. */
|
||||||
extern const char*basedir;
|
extern const char*basedir;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,21 +181,21 @@ AX_C_UNDERSCORES_TRAILING
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
AC_MSG_CHECKING(for sanity of prefix)
|
AC_MSG_CHECKING(for sanity of prefix)
|
||||||
if test X`echo "$prefix" | wc -w` != X1
|
if test `echo "$prefix" | wc -w` != 1
|
||||||
then
|
then
|
||||||
AC_MSG_ERROR(cannot configure white space in prefix: $prefix)
|
AC_MSG_ERROR(cannot configure white space in prefix: $prefix)
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT(ok)
|
AC_MSG_RESULT(ok)
|
||||||
|
|
||||||
AC_MSG_CHECKING(for sanity of exec_prefix)
|
AC_MSG_CHECKING(for sanity of exec_prefix)
|
||||||
if test X`echo "$exec_prefix" | wc -w` != X1
|
if test `echo "$exec_prefix" | wc -w` != 1
|
||||||
then
|
then
|
||||||
AC_MSG_ERROR(cannot configure white space in exec_prefix: $exec_prefix)
|
AC_MSG_ERROR(cannot configure white space in exec_prefix: $exec_prefix)
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT(ok)
|
AC_MSG_RESULT(ok)
|
||||||
|
|
||||||
AC_MSG_CHECKING(for sanity of libdir)
|
AC_MSG_CHECKING(for sanity of libdir)
|
||||||
if test X`echo "$libdir" | wc -w` != X1
|
if test `echo "$libdir" | wc -w` != 1
|
||||||
then
|
then
|
||||||
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
|
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -208,8 +208,12 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||||
o << " scope=" << scope_path(scope());
|
o << " scope=" << scope_path(scope());
|
||||||
o << " #(" << rise_time() << "," << fall_time() << ","
|
o << " #(" << rise_time() << "," << fall_time() << ","
|
||||||
<< decay_time() << ") vector_width=" << vector_width()
|
<< decay_time() << ") vector_width=" << vector_width()
|
||||||
<< " pin_count=" << pin_count()
|
<< " pin_count=" << pin_count();
|
||||||
<< " init=";
|
if (pins_are_virtual()) {
|
||||||
|
o << " pins_are_virtual" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
o << " init=";
|
||||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||||
o << pin(idx-1).get_init();
|
o << pin(idx-1).get_init();
|
||||||
|
|
||||||
|
|
|
||||||
12
elab_expr.cc
12
elab_expr.cc
|
|
@ -686,7 +686,7 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case: shift is negative (so do a left shift)
|
// Special case: shift is negative (so do a left shift)
|
||||||
// and is greater then the output width. Replace the
|
// and is greater than the output width. Replace the
|
||||||
// expression with a constant-0.
|
// expression with a constant-0.
|
||||||
if (shift < 0 && (0-shift) >= use_wid) {
|
if (shift < 0 && (0-shift) >= use_wid) {
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
|
|
@ -1790,7 +1790,9 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
||||||
two bit select expressions, and both must be
|
two bit select expressions, and both must be
|
||||||
constant. Evaluate them and pass the results back to
|
constant. Evaluate them and pass the results back to
|
||||||
the caller. */
|
the caller. */
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, lsb_wid);
|
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, lsb_wid);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
|
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
|
||||||
if (lsb_c == 0) {
|
if (lsb_c == 0) {
|
||||||
cerr << index_tail.lsb->get_fileline() << ": error: "
|
cerr << index_tail.lsb->get_fileline() << ": error: "
|
||||||
|
|
@ -1808,7 +1810,9 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
||||||
lsb = lsb_c->value().as_long();
|
lsb = lsb_c->value().as_long();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, msb_wid);
|
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, msb_wid);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||||
if (msb_c == 0) {
|
if (msb_c == 0) {
|
||||||
cerr << index_tail.msb->get_fileline() << ": error: "
|
cerr << index_tail.msb->get_fileline() << ": error: "
|
||||||
|
|
@ -1845,7 +1849,9 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
|
||||||
/* Calculate the width expression (in the lsb_ position)
|
/* Calculate the width expression (in the lsb_ position)
|
||||||
first. If the expression is not constant, error but guess 1
|
first. If the expression is not constant, error but guess 1
|
||||||
so we can keep going and find more errors. */
|
so we can keep going and find more errors. */
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
||||||
|
|
||||||
if (wid_c == 0) {
|
if (wid_c == 0) {
|
||||||
|
|
@ -2259,7 +2265,7 @@ NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (! parts_defined_flag) {
|
if (! parts_defined_flag) {
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
cerr << get_fileline() << ": debug: Part select of paramter "
|
cerr << get_fileline() << ": debug: Part select of parameter "
|
||||||
<< "has x/z bits, so resorting to 'bx result." << endl;
|
<< "has x/z bits, so resorting to 'bx result." << endl;
|
||||||
|
|
||||||
long wid = 1 + labs(par_msv-par_lsv);
|
long wid = 1 + labs(par_msv-par_lsv);
|
||||||
|
|
@ -2394,7 +2400,9 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
||||||
|
|
||||||
/* Get and evaluate the width of the index
|
/* Get and evaluate the width of the index
|
||||||
select. This must be constant. */
|
select. This must be constant. */
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||||
if (wid_ec == 0) {
|
if (wid_ec == 0) {
|
||||||
cerr << index_tail.lsb->get_fileline() << ": error: "
|
cerr << index_tail.lsb->get_fileline() << ": error: "
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
|
|
||||||
case index_component_t::SEL_IDX_DO:
|
case index_component_t::SEL_IDX_DO:
|
||||||
case index_component_t::SEL_IDX_UP: {
|
case index_component_t::SEL_IDX_UP: {
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
cerr << get_fileline() << ": error: indexed part select of "
|
cerr << get_fileline() << ": error: indexed part select of "
|
||||||
|
|
@ -437,7 +439,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
|
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
|
||||||
|
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
|
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
cerr << get_fileline() << ": error: array " << sig->name()
|
cerr << get_fileline() << ": error: array " << sig->name()
|
||||||
|
|
|
||||||
|
|
@ -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
|
* 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
|
||||||
|
|
@ -496,7 +496,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
// use) the genvar itself, so we can evaluate this expression
|
// use) the genvar itself, so we can evaluate this expression
|
||||||
// the same way any other parameter value is evaluated.
|
// the same way any other parameter value is evaluated.
|
||||||
probe_expr_width(des, container, loop_init);
|
probe_expr_width(des, container, loop_init);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||||
if (init == 0) {
|
if (init == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||||
|
|
@ -526,7 +528,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
container->genvar_tmp = loop_index;
|
container->genvar_tmp = loop_index;
|
||||||
container->genvar_tmp_val = genvar;
|
container->genvar_tmp_val = genvar;
|
||||||
probe_expr_width(des, container, loop_test);
|
probe_expr_width(des, container, loop_test);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
||||||
if (test == 0) {
|
if (test == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||||
|
|
@ -579,7 +583,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
|
|
||||||
// Calculate the step for the loop variable.
|
// Calculate the step for the loop variable.
|
||||||
probe_expr_width(des, container, loop_step);
|
probe_expr_width(des, container, loop_step);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||||
if (step == 0) {
|
if (step == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||||
|
|
@ -611,7 +617,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
|
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
|
||||||
{
|
{
|
||||||
probe_expr_width(des, container, loop_test);
|
probe_expr_width(des, container, loop_test);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
||||||
if (test == 0) {
|
if (test == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||||
|
|
@ -671,7 +679,9 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||||
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||||
{
|
{
|
||||||
probe_expr_width(des, container, loop_test);
|
probe_expr_width(des, container, loop_test);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
||||||
if (case_value_co == 0) {
|
if (case_value_co == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
||||||
|
|
@ -702,9 +712,17 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||||
bool match_flag = false;
|
bool match_flag = false;
|
||||||
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
|
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
|
||||||
probe_expr_width(des, container, item->item_test[idx]);
|
probe_expr_width(des, container, item->item_test[idx]);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
|
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
||||||
assert(item_value_co);
|
if (item_value_co == 0) {
|
||||||
|
cerr << get_fileline() << ": error: Cannot evaluate "
|
||||||
|
<< " genvar case item expression: "
|
||||||
|
<< *item->item_test[idx] << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug_scopes)
|
if (debug_scopes)
|
||||||
cerr << get_fileline() << ": debug: Generate case "
|
cerr << get_fileline() << ": debug: Generate case "
|
||||||
|
|
@ -952,8 +970,10 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||||
{
|
{
|
||||||
if (msb_) probe_expr_width(des, sc, msb_);
|
if (msb_) probe_expr_width(des, sc, msb_);
|
||||||
if (lsb_) probe_expr_width(des, sc, lsb_);
|
if (lsb_) probe_expr_width(des, sc, lsb_);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
||||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -843,8 +843,8 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
/*
|
/*
|
||||||
* Elaborate a source wire. The "wire" is the declaration of wires,
|
* Elaborate a source wire. The "wire" is the declaration of wires,
|
||||||
* registers, ports and memories. The parser has already merged the
|
* registers, ports and memories. The parser has already merged the
|
||||||
* multiple properties of a wire (i.e., "input wire") so come the
|
* multiple properties of a wire (i.e., "input wire"), so come the
|
||||||
* elaboration this creates an object in the design that represent the
|
* elaboration this creates an object in the design that represents the
|
||||||
* defined item.
|
* defined item.
|
||||||
*/
|
*/
|
||||||
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
|
|
@ -1108,6 +1108,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
|
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
|
||||||
: new NetNet(scope, name_, wtype, msb, lsb);
|
: new NetNet(scope, name_, wtype, msb, lsb);
|
||||||
|
|
||||||
|
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
|
||||||
|
|
||||||
ivl_variable_type_t use_data_type = data_type_;
|
ivl_variable_type_t use_data_type = data_type_;
|
||||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||||
use_data_type = IVL_VT_LOGIC;
|
use_data_type = IVL_VT_LOGIC;
|
||||||
|
|
|
||||||
|
|
@ -234,8 +234,10 @@ unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
|
||||||
gates, then I am expected to make more than one
|
gates, then I am expected to make more than one
|
||||||
gate. Figure out how many are desired. */
|
gate. Figure out how many are desired. */
|
||||||
if (msb_) {
|
if (msb_) {
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
|
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
|
||||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
|
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
|
|
||||||
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
||||||
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||||
|
|
||||||
if (debug_eval_tree) {
|
if (debug_eval_tree) {
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
<< "Partially evalutate " << *this
|
<< "Partially evaluate " << *this
|
||||||
<< " using (a+2)-1 --> (a+1) transform." << endl;
|
<< " using (a+2)-1 --> (a+1) transform." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -719,16 +719,20 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
{
|
{
|
||||||
/* First, synthesize the operands. */
|
/* First, synthesize the operands. */
|
||||||
|
unsigned nparms = parms_.count();
|
||||||
NetNet**tmp = new NetNet*[parms_.count()];
|
NetNet**tmp = new NetNet*[parms_.count()];
|
||||||
bool flag = true;
|
bool flag = true;
|
||||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||||
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
|
if (parms_[idx]->expr_width() == 0) {
|
||||||
if (tmp[idx] == 0)
|
tmp[idx] = 0;
|
||||||
flag = false;
|
nparms -= 1;
|
||||||
|
} else {
|
||||||
|
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
|
||||||
|
if (tmp[idx] == 0) flag = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag == false)
|
if (flag == false) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
ivl_assert(*this, tmp[0]);
|
ivl_assert(*this, tmp[0]);
|
||||||
|
|
||||||
|
|
@ -740,7 +744,7 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
|
|
||||||
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
|
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
|
||||||
osig->vector_width(),
|
osig->vector_width(),
|
||||||
parms_.count() * repeat());
|
nparms * repeat());
|
||||||
concat->set_line(*this);
|
concat->set_line(*this);
|
||||||
des->add_node(concat);
|
des->add_node(concat);
|
||||||
connect(concat->pin(0), osig->pin(0));
|
connect(concat->pin(0), osig->pin(0));
|
||||||
|
|
@ -750,7 +754,7 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
|
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
|
||||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||||
unsigned concat_item = parms_.count()-idx-1;
|
unsigned concat_item = parms_.count()-idx-1;
|
||||||
ivl_assert(*this, tmp[concat_item]);
|
if (tmp[concat_item] == 0) continue;
|
||||||
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
|
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
|
||||||
cur_pin += 1;
|
cur_pin += 1;
|
||||||
count_input_width += tmp[concat_item]->vector_width();
|
count_input_width += tmp[concat_item]->vector_width();
|
||||||
|
|
@ -773,6 +777,11 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope, NetExpr*)
|
||||||
{
|
{
|
||||||
perm_string path = scope->local_symbol();
|
perm_string path = scope->local_symbol();
|
||||||
unsigned width=expr_width();
|
unsigned width=expr_width();
|
||||||
|
if (width == 0) {
|
||||||
|
cerr << get_fileline() << ": internal error: "
|
||||||
|
<< "Found a zero width constant!" << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
|
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
|
|
|
||||||
|
|
@ -499,65 +499,3 @@ already seems to exist amongst VCD viewers in the wild, this behavior
|
||||||
seems to be acceptable according to the standard, is a better mirror
|
seems to be acceptable according to the standard, is a better mirror
|
||||||
of 4-value behavior in the dead zone, and appears more user friendly
|
of 4-value behavior in the dead zone, and appears more user friendly
|
||||||
when viewed by reasonable viewers.
|
when viewed by reasonable viewers.
|
||||||
|
|
||||||
|
|
||||||
$Id: ieee1364-notes.txt,v 1.19 2007/04/18 02:36:13 steve Exp $
|
|
||||||
$Log: ieee1364-notes.txt,v $
|
|
||||||
Revision 1.19 2007/04/18 02:36:13 steve
|
|
||||||
Put to iverilog wiki for further notes.
|
|
||||||
|
|
||||||
Revision 1.18 2007/03/22 16:08:16 steve
|
|
||||||
Spelling fixes from Larry
|
|
||||||
|
|
||||||
Revision 1.17 2003/07/15 03:49:22 steve
|
|
||||||
Spelling fixes.
|
|
||||||
|
|
||||||
Revision 1.16 2003/04/14 03:40:21 steve
|
|
||||||
Make some effort to preserve bits while
|
|
||||||
operating on constant values.
|
|
||||||
|
|
||||||
Revision 1.15 2003/02/16 23:39:08 steve
|
|
||||||
NaN in dead zones of VCD dumps.
|
|
||||||
|
|
||||||
Revision 1.14 2003/02/06 17:51:36 steve
|
|
||||||
Edge of vectors notes.
|
|
||||||
|
|
||||||
Revision 1.13 2002/08/20 04:11:53 steve
|
|
||||||
Support parameters with defined ranges.
|
|
||||||
|
|
||||||
Revision 1.12 2002/06/11 03:34:33 steve
|
|
||||||
Spelling patch (Larry Doolittle)
|
|
||||||
|
|
||||||
Revision 1.11 2002/04/27 02:38:04 steve
|
|
||||||
Support selecting bits from parameters.
|
|
||||||
|
|
||||||
Revision 1.10 2002/03/31 01:54:13 steve
|
|
||||||
Notes about scheduling
|
|
||||||
|
|
||||||
Revision 1.9 2002/01/26 02:08:07 steve
|
|
||||||
Handle x in l-value of set/x
|
|
||||||
|
|
||||||
Revision 1.8 2001/08/01 05:17:31 steve
|
|
||||||
Accept empty port lists to module instantiation.
|
|
||||||
|
|
||||||
Revision 1.7 2001/02/17 05:27:31 steve
|
|
||||||
I allow function ports to have types.
|
|
||||||
|
|
||||||
Revision 1.6 2001/02/12 16:48:04 steve
|
|
||||||
Rant about bit widths.
|
|
||||||
|
|
||||||
Revision 1.5 2001/01/02 17:28:08 steve
|
|
||||||
Resolve repeat ambiguity in favor of loop.
|
|
||||||
|
|
||||||
Revision 1.4 2001/01/01 19:12:35 steve
|
|
||||||
repeat loops ambiguity.
|
|
||||||
|
|
||||||
Revision 1.3 2000/12/15 00:21:46 steve
|
|
||||||
rounding of time and x in primitives.
|
|
||||||
|
|
||||||
Revision 1.2 2000/11/19 22:03:04 steve
|
|
||||||
Integer parameter comments.
|
|
||||||
|
|
||||||
Revision 1.1 2000/07/23 18:06:31 steve
|
|
||||||
Document ieee1364 issues.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
Icarus Verilog LOADABLE TARGET API (ivl_target)
|
Icarus Verilog LOADABLE TARGET API (ivl_target)
|
||||||
|
|
||||||
Copyright 2002 Stephen Williams <steve@icarus.com>
|
Copyright 2002 Stephen Williams <steve@icarus.com>
|
||||||
$Id: ivl_target.txt,v 1.3 2002/06/11 03:34:33 steve Exp $
|
|
||||||
|
|
||||||
|
|
||||||
The ivl_target API is the interface available to modules that the
|
The ivl_target API is the interface available to modules that the
|
||||||
|
|
@ -38,14 +37,3 @@ other LPM device with outputs.
|
||||||
|
|
||||||
There are ivl_lpm_size() input ports, each with the width
|
There are ivl_lpm_size() input ports, each with the width
|
||||||
ivl_lpm_data2_width(). The actual nexus is indexed by ivl_lpm_data2().
|
ivl_lpm_data2_width(). The actual nexus is indexed by ivl_lpm_data2().
|
||||||
|
|
||||||
$Log: ivl_target.txt,v $
|
|
||||||
Revision 1.3 2002/06/11 03:34:33 steve
|
|
||||||
Spelling patch (Larry Doolittle)
|
|
||||||
|
|
||||||
Revision 1.2 2002/03/17 19:31:17 steve
|
|
||||||
Add API to support user defined function.
|
|
||||||
|
|
||||||
Revision 1.1 2002/03/09 02:10:22 steve
|
|
||||||
Add the NetUserFunc netlist node.
|
|
||||||
|
|
||||||
|
|
|
||||||
11
main.cc
11
main.cc
|
|
@ -128,6 +128,12 @@ bool debug_elab_pexpr = false;
|
||||||
bool debug_synth2 = false;
|
bool debug_synth2 = false;
|
||||||
bool debug_optimizer = false;
|
bool debug_optimizer = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Miscellaneous flags.
|
||||||
|
*/
|
||||||
|
bool disable_virtual_pins = false;
|
||||||
|
unsigned long array_size_limit = 16777216; // Minimum required by IEEE-1364?
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verbose messages enabled.
|
* Verbose messages enabled.
|
||||||
*/
|
*/
|
||||||
|
|
@ -709,6 +715,11 @@ int main(int argc, char*argv[])
|
||||||
cout << endl << "PARSING INPUT" << endl;
|
cout << endl << "PARSING INPUT" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"];
|
||||||
|
if (flag_tmp) disable_virtual_pins = strcmp(flag_tmp,"true")==0;
|
||||||
|
flag_tmp = flags["ARRAY_SIZE_LIMIT"];
|
||||||
|
if (flag_tmp) array_size_limit = strtoul(flag_tmp,NULL,0);
|
||||||
|
|
||||||
/* Parse the input. Make the pform. */
|
/* Parse the input. Make the pform. */
|
||||||
int rc = pform_parse(argv[optind]);
|
int rc = pform_parse(argv[optind]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ void Link::unlink()
|
||||||
|
|
||||||
bool Link::is_equal(const Link&that) const
|
bool Link::is_equal(const Link&that) const
|
||||||
{
|
{
|
||||||
return (node_ == that.node_) && (pin_ == that.pin_);
|
return (get_obj() == that.get_obj()) && (get_pin() == that.get_pin());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Link::is_linked() const
|
bool Link::is_linked() const
|
||||||
|
|
|
||||||
94
netlist.cc
94
netlist.cc
|
|
@ -172,26 +172,51 @@ Link* find_next_output(Link*lnk)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPins::NetPins(unsigned npins)
|
void NetPins::devirtualize_pins(void)
|
||||||
: npins_(npins)
|
|
||||||
{
|
{
|
||||||
|
if (pins_) return;
|
||||||
|
if (npins_ > array_size_limit) {
|
||||||
|
cerr << get_fileline() << ": error: pin count " << npins_ <<
|
||||||
|
" exceeds " << array_size_limit <<
|
||||||
|
" (set by -pARRAY_SIZE_LIMIT)" << endl;
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
if (debug_optimizer && npins_ > 1000) cerr << "debug: devirtualizing " << npins_ << " pins." << endl;
|
||||||
|
|
||||||
pins_ = new Link[npins_];
|
pins_ = new Link[npins_];
|
||||||
pins_[0].pin_zero_ = true;
|
pins_[0].pin_zero_ = true;
|
||||||
pins_[0].node_ = this;
|
pins_[0].node_ = this;
|
||||||
|
pins_[0].dir_ = default_dir_;
|
||||||
|
pins_[0].init_ = default_init_;
|
||||||
|
|
||||||
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
|
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
|
||||||
pins_[idx].pin_zero_ = false;
|
pins_[idx].pin_zero_ = false;
|
||||||
pins_[idx].pin_ = idx;
|
pins_[idx].pin_ = idx;
|
||||||
|
pins_[idx].dir_ = default_dir_;
|
||||||
|
pins_[idx].init_ = default_init_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetPins::pins_are_virtual(void) const
|
||||||
|
{
|
||||||
|
return pins_ == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetPins::NetPins(unsigned npins)
|
||||||
|
: npins_(npins)
|
||||||
|
{
|
||||||
|
pins_ = NULL; // Wait until someone asks.
|
||||||
|
if (disable_virtual_pins) devirtualize_pins(); // Ask. Bummer.
|
||||||
|
}
|
||||||
|
|
||||||
NetPins::~NetPins()
|
NetPins::~NetPins()
|
||||||
{
|
{
|
||||||
delete[]pins_;
|
if (pins_) delete[]pins_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Link& NetPins::pin(unsigned idx)
|
Link& NetPins::pin(unsigned idx)
|
||||||
{
|
{
|
||||||
|
if (!pins_) devirtualize_pins();
|
||||||
if (idx >= npins_) {
|
if (idx >= npins_) {
|
||||||
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
|
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
|
||||||
<< " out of bounds("<<npins_<<")" << endl;
|
<< " out of bounds("<<npins_<<")" << endl;
|
||||||
|
|
@ -207,11 +232,27 @@ Link& NetPins::pin(unsigned idx)
|
||||||
|
|
||||||
const Link& NetPins::pin(unsigned idx) const
|
const Link& NetPins::pin(unsigned idx) const
|
||||||
{
|
{
|
||||||
|
if (!pins_ && !disable_virtual_pins) {
|
||||||
|
cerr << get_fileline() << ": internal error: pin is unexpectedly"
|
||||||
|
" virtual, try again with -pDISABLE_VIRTUAL_PINS=true" << endl;
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
assert(pins_);
|
||||||
assert(idx < npins_);
|
assert(idx < npins_);
|
||||||
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
|
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
|
||||||
return pins_[idx];
|
return pins_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetPins::set_default_dir(Link::DIR d)
|
||||||
|
{
|
||||||
|
default_dir_ = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPins::set_default_init(verinum::V val)
|
||||||
|
{
|
||||||
|
default_init_ = val;
|
||||||
|
}
|
||||||
|
|
||||||
bool NetPins::is_linked(void)
|
bool NetPins::is_linked(void)
|
||||||
{
|
{
|
||||||
bool linked_flag = false;
|
bool linked_flag = false;
|
||||||
|
|
@ -228,6 +269,11 @@ bool NetPins::is_linked(void)
|
||||||
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
|
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
|
||||||
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
|
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
|
||||||
{
|
{
|
||||||
|
/* Don't
|
||||||
|
ivl_assert(*this, np > 0);
|
||||||
|
* because it would happen before we get to print a useful
|
||||||
|
* message in the NetNet constructor
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
NetObj::~NetObj()
|
NetObj::~NetObj()
|
||||||
|
|
@ -269,6 +315,9 @@ NetBranch::~NetBranch()
|
||||||
NetBus::NetBus(NetScope*s, unsigned pin_count__)
|
NetBus::NetBus(NetScope*s, unsigned pin_count__)
|
||||||
: NetObj(s, perm_string::literal(""), pin_count__)
|
: NetObj(s, perm_string::literal(""), pin_count__)
|
||||||
{
|
{
|
||||||
|
for (unsigned idx = 0 ; idx <pin_count__ ; idx += 1) {
|
||||||
|
pin(idx).set_dir(Link::PASSIVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetBus::~NetBus()
|
NetBus::~NetBus()
|
||||||
|
|
@ -479,7 +528,11 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||||
|
|
||||||
void NetNet::initialize_value_and_dir(verinum::V init_value, Link::DIR dir)
|
void NetNet::initialize_value_and_dir(verinum::V init_value, Link::DIR dir)
|
||||||
{
|
{
|
||||||
if (1) {
|
if (pins_are_virtual()) {
|
||||||
|
if (0) cerr << "NetNet setting Link default value and dir" << endl;
|
||||||
|
set_default_init(init_value);
|
||||||
|
set_default_dir(dir);
|
||||||
|
} else {
|
||||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||||
pin(idx).set_dir(dir);
|
pin(idx).set_dir(dir);
|
||||||
pin(idx).set_init(init_value);
|
pin(idx).set_init(init_value);
|
||||||
|
|
@ -524,10 +577,16 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
|
|
||||||
static unsigned calculate_count(long s, long e)
|
static unsigned calculate_count(long s, long e)
|
||||||
{
|
{
|
||||||
if (s >= e)
|
unsigned long r;
|
||||||
return s - e + 1;
|
if (s >= e) {
|
||||||
else
|
r = s - e;
|
||||||
return e - s + 1;
|
} else {
|
||||||
|
r = e - s;
|
||||||
|
}
|
||||||
|
if (r >= UINT_MAX) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return r + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
|
|
@ -538,7 +597,11 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
|
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
|
||||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
assert(s);
|
ivl_assert(*this, s);
|
||||||
|
if (pin_count() == 0) {
|
||||||
|
cerr << "Array too big [" << array_s << ":" << array_e << "]" << endl;
|
||||||
|
ivl_assert(*this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
verinum::V init_value = verinum::Vz;
|
verinum::V init_value = verinum::Vz;
|
||||||
Link::DIR dir = Link::PASSIVE;
|
Link::DIR dir = Link::PASSIVE;
|
||||||
|
|
@ -732,7 +795,9 @@ bool NetNet::array_addr_swapped() const
|
||||||
|
|
||||||
unsigned NetNet::array_count() const
|
unsigned NetNet::array_count() const
|
||||||
{
|
{
|
||||||
return calculate_count(s0_, e0_);
|
unsigned c = calculate_count(s0_, e0_);
|
||||||
|
ivl_assert(*this, c > 0);
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetNet::array_index_is_valid(long sb) const
|
bool NetNet::array_index_is_valid(long sb) const
|
||||||
|
|
@ -810,7 +875,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||||
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
|
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
|
||||||
off_(off), wid_(wid), dir_(dir__)
|
off_(off), wid_(wid), dir_(dir__)
|
||||||
{
|
{
|
||||||
connect(pin(1), sig->pin(0));
|
|
||||||
set_line(*sig);
|
set_line(*sig);
|
||||||
|
|
||||||
switch (dir_) {
|
switch (dir_) {
|
||||||
|
|
@ -823,6 +887,8 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||||
pin(1).set_dir(Link::OUTPUT);
|
pin(1).set_dir(Link::OUTPUT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(pin(1), sig->pin(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||||
|
|
@ -830,9 +896,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||||
: NetNode(sig->scope(), sig->scope()->local_symbol(), 3),
|
: NetNode(sig->scope(), sig->scope()->local_symbol(), 3),
|
||||||
off_(0), wid_(wid), dir_(VP)
|
off_(0), wid_(wid), dir_(VP)
|
||||||
{
|
{
|
||||||
connect(pin(1), sig->pin(0));
|
|
||||||
connect(pin(2), sel->pin(0));
|
|
||||||
|
|
||||||
switch (dir_) {
|
switch (dir_) {
|
||||||
case NetPartSelect::VP:
|
case NetPartSelect::VP:
|
||||||
pin(0).set_dir(Link::OUTPUT);
|
pin(0).set_dir(Link::OUTPUT);
|
||||||
|
|
@ -844,6 +907,9 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pin(2).set_dir(Link::INPUT);
|
pin(2).set_dir(Link::INPUT);
|
||||||
|
|
||||||
|
connect(pin(1), sig->pin(0));
|
||||||
|
connect(pin(2), sel->pin(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPartSelect::~NetPartSelect()
|
NetPartSelect::~NetPartSelect()
|
||||||
|
|
|
||||||
|
|
@ -193,11 +193,17 @@ class NetPins : public LineInfo {
|
||||||
const Link&pin(unsigned idx) const;
|
const Link&pin(unsigned idx) const;
|
||||||
|
|
||||||
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
|
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
|
||||||
|
void set_default_dir(Link::DIR d);
|
||||||
|
void set_default_init(verinum::V val);
|
||||||
bool is_linked();
|
bool is_linked();
|
||||||
|
bool pins_are_virtual(void) const;
|
||||||
|
void devirtualize_pins(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Link*pins_;
|
Link*pins_;
|
||||||
const unsigned npins_;
|
const unsigned npins_;
|
||||||
|
Link::DIR default_dir_;
|
||||||
|
verinum::V default_init_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* =========
|
/* =========
|
||||||
|
|
@ -3256,6 +3262,7 @@ class NetEBAdd : public NetEBinary {
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
virtual bool set_width(unsigned w, bool last_chance);
|
virtual bool set_width(unsigned w, bool last_chance);
|
||||||
|
virtual void cast_signed(bool sign_flag);
|
||||||
virtual NetEBAdd* dup_expr() const;
|
virtual NetEBAdd* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
@ -3278,6 +3285,7 @@ class NetEBDiv : public NetEBinary {
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
virtual bool set_width(unsigned w, bool last_chance);
|
virtual bool set_width(unsigned w, bool last_chance);
|
||||||
|
virtual void cast_signed(bool sign_flag);
|
||||||
virtual NetEBDiv* dup_expr() const;
|
virtual NetEBDiv* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
@ -3408,6 +3416,7 @@ class NetEBMult : public NetEBinary {
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
virtual bool set_width(unsigned w, bool last_chance);
|
virtual bool set_width(unsigned w, bool last_chance);
|
||||||
|
virtual void cast_signed(bool sign_flag);
|
||||||
virtual NetEBMult* dup_expr() const;
|
virtual NetEBMult* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
|
||||||
47
netlist.txt
47
netlist.txt
|
|
@ -16,7 +16,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ident "$Id: netlist.txt,v 1.10 2000/07/23 18:06:15 steve Exp $"
|
|
||||||
|
|
||||||
|
|
||||||
Note that the netlist.h header contains detailed descriptions of how
|
Note that the netlist.h header contains detailed descriptions of how
|
||||||
|
|
@ -291,49 +290,3 @@ values. These are filled in during scope elaboration and are used in
|
||||||
subsequent elaboration phases to arrange for scaling of delays. This
|
subsequent elaboration phases to arrange for scaling of delays. This
|
||||||
information can also be used by the code generator to scale times back
|
information can also be used by the code generator to scale times back
|
||||||
to the units of the scope, if that is desired.
|
to the units of the scope, if that is desired.
|
||||||
|
|
||||||
$Log: netlist.txt,v $
|
|
||||||
Revision 1.10 2000/07/23 18:06:15 steve
|
|
||||||
Document time scale in netlists.
|
|
||||||
|
|
||||||
Revision 1.9 2000/07/14 06:12:57 steve
|
|
||||||
Move inital value handling from NetNet to Nexus
|
|
||||||
objects. This allows better propogation of inital
|
|
||||||
values.
|
|
||||||
|
|
||||||
Clean up constant propagation a bit to account
|
|
||||||
for regs that are not really values.
|
|
||||||
|
|
||||||
Revision 1.8 2000/03/08 04:36:54 steve
|
|
||||||
Redesign the implementation of scopes and parameters.
|
|
||||||
I now generate the scopes and notice the parameters
|
|
||||||
in a separate pass over the pform. Once the scopes
|
|
||||||
are generated, I can process overrides and evalutate
|
|
||||||
paremeters before elaboration begins.
|
|
||||||
|
|
||||||
Revision 1.7 1999/11/28 23:42:02 steve
|
|
||||||
NetESignal object no longer need to be NetNode
|
|
||||||
objects. Let them keep a pointer to NetNet objects.
|
|
||||||
|
|
||||||
Revision 1.6 1999/11/21 00:13:09 steve
|
|
||||||
Support memories in continuous assignments.
|
|
||||||
|
|
||||||
Revision 1.5 1999/11/02 04:55:34 steve
|
|
||||||
Add the synthesize method to NetExpr to handle
|
|
||||||
synthesis of expressions, and use that method
|
|
||||||
to improve r-value handling of LPM_FF synthesis.
|
|
||||||
|
|
||||||
Modify the XNF target to handle LPM_FF objects.
|
|
||||||
|
|
||||||
Revision 1.4 1999/09/29 00:03:27 steve
|
|
||||||
Spelling fixes from Larry.
|
|
||||||
|
|
||||||
Revision 1.3 1999/07/24 02:11:20 steve
|
|
||||||
Elaborate task input ports.
|
|
||||||
|
|
||||||
Revision 1.2 1999/07/21 01:15:29 steve
|
|
||||||
Document netlist semantics.
|
|
||||||
|
|
||||||
Revision 1.1 1999/05/27 04:13:08 steve
|
|
||||||
Handle expression bit widths with non-fatal errors.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# This script makes a release from a git repository. The input is
|
||||||
|
# the number for a snapshot and the path to a temporary directory.
|
||||||
|
# for example:
|
||||||
|
#
|
||||||
|
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||||
|
#
|
||||||
|
# The above assumes that there is a tag "v0_9_1" at the point
|
||||||
|
# to be released. (The tag has the "v", but the argument to this
|
||||||
|
# script does not have the "v"). This script extracts based on the
|
||||||
|
# tag, uses the temporary directory to stage intermediate results,
|
||||||
|
# and finally creates a file called verilog-0.9.1.tar.gz that
|
||||||
|
# contains the release ready to go.
|
||||||
|
#
|
||||||
|
# The complete steps to make a release x.y.z generally are:
|
||||||
|
#
|
||||||
|
# git tag -a v0_9_1
|
||||||
|
# (Make the tag in the local git repository.)
|
||||||
|
#
|
||||||
|
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||||
|
# (Make the snapshot bundle verilog-0.9.1.tar.gz)
|
||||||
|
#
|
||||||
|
# git push --tags
|
||||||
|
# (Publish the tag to the repository.)
|
||||||
|
#
|
||||||
|
id=$1
|
||||||
|
destdir=$2
|
||||||
|
|
||||||
|
# The git tag to use.
|
||||||
|
tag="v"`echo $id | tr '.' '_'`
|
||||||
|
|
||||||
|
# The prefix is the directory that contains the extracted files
|
||||||
|
# of the bundle. This is also the name of the bundle file itself.
|
||||||
|
prefix="verilog-$id"
|
||||||
|
|
||||||
|
if [ ! -d $destdir ]; then
|
||||||
|
echo "ERROR: Directory $destdir does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e $destdir/$prefix ]; then
|
||||||
|
echo "ERROR: $destdir/$prefix already exists."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Exporting $tag to $destdir/$prefix..."
|
||||||
|
git archive --prefix="$prefix/" $tag | ( cd "$destdir" && tar xf - )
|
||||||
|
|
||||||
|
versionh="$destdir/$prefix/version_tag.h"
|
||||||
|
echo "Create $versionh ..."
|
||||||
|
echo "#ifndef VERSION_TAG" > $versionh
|
||||||
|
echo "#define VERSION_TAG \"$tag\"" >> $versionh
|
||||||
|
echo "#endif" >> $versionh
|
||||||
|
|
||||||
|
echo "Running autoconf.sh..."
|
||||||
|
( cd $destdir/$prefix && sh autoconf.sh )
|
||||||
|
|
||||||
|
echo "Making bundle $prefix.tar.gz..."
|
||||||
|
tar czf $prefix.tar.gz --exclude=autom4te.cache -C "$destdir" $prefix
|
||||||
|
|
||||||
|
echo "Removing temporary $destdir/$prefix..."
|
||||||
|
rm -rf "$destdir/$prefix"
|
||||||
|
|
||||||
|
echo done
|
||||||
|
|
@ -47,9 +47,11 @@ fi
|
||||||
echo "Exporting $tag to $destdir/$prefix..."
|
echo "Exporting $tag to $destdir/$prefix..."
|
||||||
git archive --prefix="$prefix/" $tag | ( cd "$destdir" && tar xf - )
|
git archive --prefix="$prefix/" $tag | ( cd "$destdir" && tar xf - )
|
||||||
|
|
||||||
versionh="$destdir/$prefix/version.h"
|
versionh="$destdir/$prefix/version_tag.h"
|
||||||
echo "Create $versionh ..."
|
echo "Create $versionh ..."
|
||||||
echo "#define VERSION_TAG \"$tag\"" > $versionh
|
echo "#ifndef VERSION_TAG" > $versionh
|
||||||
|
echo "#define VERSION_TAG \"$tag\"" >> $versionh
|
||||||
|
echo "#endif" >> $versionh
|
||||||
|
|
||||||
echo "Running autoconf.sh..."
|
echo "Running autoconf.sh..."
|
||||||
( cd $destdir/$prefix && sh autoconf.sh )
|
( cd $destdir/$prefix && sh autoconf.sh )
|
||||||
|
|
|
||||||
38
set_width.cc
38
set_width.cc
|
|
@ -106,6 +106,18 @@ bool NetEBAdd::set_width(unsigned w, bool)
|
||||||
return wid == w;
|
return wid == w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetEBAdd::cast_signed(bool sign_flag)
|
||||||
|
{
|
||||||
|
if (has_sign() == sign_flag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sign_flag == false) {
|
||||||
|
left_->cast_signed(sign_flag);
|
||||||
|
right_->cast_signed(sign_flag);
|
||||||
|
}
|
||||||
|
cast_signed_base_(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The bitwise logical operators have operands the same size as the
|
* The bitwise logical operators have operands the same size as the
|
||||||
* result. Anything else is a mess. I first try to get the operands to
|
* result. Anything else is a mess. I first try to get the operands to
|
||||||
|
|
@ -168,6 +180,19 @@ bool NetEBDiv::set_width(unsigned w, bool)
|
||||||
return w == expr_width();
|
return w == expr_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetEBDiv::cast_signed(bool sign_flag)
|
||||||
|
{
|
||||||
|
if (has_sign() == sign_flag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sign_flag == false) {
|
||||||
|
left_->cast_signed(sign_flag);
|
||||||
|
right_->cast_signed(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
cast_signed_base_(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
bool NetEBLogic::set_width(unsigned w, bool)
|
bool NetEBLogic::set_width(unsigned w, bool)
|
||||||
{
|
{
|
||||||
bool flag;
|
bool flag;
|
||||||
|
|
@ -192,6 +217,19 @@ bool NetEBMult::set_width(unsigned w, bool)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetEBMult::cast_signed(bool sign_flag)
|
||||||
|
{
|
||||||
|
if (has_sign() == sign_flag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sign_flag == false) {
|
||||||
|
left_->cast_signed(sign_flag);
|
||||||
|
right_->cast_signed(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
cast_signed_base_(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
bool NetEBPow::set_width(unsigned w, bool last_chance)
|
bool NetEBPow::set_width(unsigned w, bool last_chance)
|
||||||
{
|
{
|
||||||
return w == expr_width();
|
return w == expr_width();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
# $Id: README-solaris_pkg.txt,v 1.3 2007/02/26 19:49:49 steve Exp $
|
|
||||||
|
|
||||||
Notes about the solaris package.
|
Notes about the solaris package.
|
||||||
|
|
||||||
I. Installing a prebuilt solaris package
|
I. Installing a prebuilt solaris package
|
||||||
|
|
|
||||||
12
t-dll-api.cc
12
t-dll-api.cc
|
|
@ -1893,10 +1893,16 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
|
||||||
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
|
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
|
||||||
{
|
{
|
||||||
assert(word < net->array_words);
|
assert(word < net->array_words);
|
||||||
if (net->array_words > 1)
|
if (net->array_words > 1) {
|
||||||
return net->pins[word];
|
if (net->pins) {
|
||||||
else
|
return net->pins[word];
|
||||||
|
} else {
|
||||||
|
cerr << "AACK! ivl_signal_nex() returning NULL" << endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return net->pin;
|
return net->pin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int ivl_signal_msb(ivl_signal_t net)
|
extern "C" int ivl_signal_msb(ivl_signal_t net)
|
||||||
|
|
|
||||||
13
t-dll.cc
13
t-dll.cc
|
|
@ -2560,12 +2560,22 @@ void dll_target::signal(const NetNet*net)
|
||||||
obj->array_base = net->array_first();
|
obj->array_base = net->array_first();
|
||||||
obj->array_words = net->array_count();
|
obj->array_words = net->array_count();
|
||||||
obj->array_addr_swapped = net->array_addr_swapped() ? 1 : 0;
|
obj->array_addr_swapped = net->array_addr_swapped() ? 1 : 0;
|
||||||
|
|
||||||
|
assert(obj->array_words == net->pin_count());
|
||||||
|
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: "
|
||||||
|
"t-dll creating nexus array " << obj->array_words << " long" << endl;
|
||||||
|
if (obj->array_words > 1 && net->pins_are_virtual()) {
|
||||||
|
obj->pins = NULL;
|
||||||
|
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: "
|
||||||
|
"t-dll used NULL for big nexus array" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (obj->array_words > 1)
|
if (obj->array_words > 1)
|
||||||
obj->pins = new ivl_nexus_t[obj->array_words];
|
obj->pins = new ivl_nexus_t[obj->array_words];
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
|
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
|
||||||
|
|
||||||
const Nexus*nex = net->pin(idx).nexus();
|
const Nexus*nex = net->pins_are_virtual() ? 0 : net->pin(idx).nexus();
|
||||||
if (nex == 0) {
|
if (nex == 0) {
|
||||||
// Special case: This pin is connected to
|
// Special case: This pin is connected to
|
||||||
// nothing. This can happen, for example, if the
|
// nothing. This can happen, for example, if the
|
||||||
|
|
@ -2597,6 +2607,7 @@ void dll_target::signal(const NetNet*net)
|
||||||
obj->pin = tmp;
|
obj->pin = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: t-dll done with big nexus array" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dll_target::signal_paths(const NetNet*net)
|
bool dll_target::signal_paths(const NetNet*net)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog
|
FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog
|
||||||
|
|
||||||
Copyright 2001 Stephen Williams
|
Copyright 2001 Stephen Williams
|
||||||
$Id: fpga.txt,v 1.12 2005/09/19 21:45:36 steve Exp $
|
|
||||||
|
|
||||||
The FPGA code generator supports a variety of FPGA devices, writing
|
The FPGA code generator supports a variety of FPGA devices, writing
|
||||||
XNF or EDIF depending on the target. You can select the architecture
|
XNF or EDIF depending on the target. You can select the architecture
|
||||||
|
|
@ -186,42 +185,3 @@ Compile a single-file design with command line tools like so:
|
||||||
% map -o map.ncd foo.ngd
|
% map -o map.ncd foo.ngd
|
||||||
% par -w map.ncd foo.ncd
|
% par -w map.ncd foo.ncd
|
||||||
|
|
||||||
---
|
|
||||||
$Log: fpga.txt,v $
|
|
||||||
Revision 1.12 2005/09/19 21:45:36 steve
|
|
||||||
Spelling patches from Larry.
|
|
||||||
|
|
||||||
Revision 1.11 2003/08/07 05:17:34 steve
|
|
||||||
Add arch=lpm to the documentation.
|
|
||||||
|
|
||||||
Revision 1.10 2003/07/04 03:57:19 steve
|
|
||||||
Allow attributes on Verilog 2001 port declarations.
|
|
||||||
|
|
||||||
Revision 1.9 2003/07/04 01:08:03 steve
|
|
||||||
PAD attribute can be used to assign pins.
|
|
||||||
|
|
||||||
Revision 1.8 2003/07/02 00:26:49 steve
|
|
||||||
Fix spelling of part= flag.
|
|
||||||
|
|
||||||
Revision 1.7 2003/03/24 02:28:38 steve
|
|
||||||
Document the virtex2 architecture.
|
|
||||||
|
|
||||||
Revision 1.6 2003/03/24 00:47:54 steve
|
|
||||||
Add new virtex2 architecture family, and
|
|
||||||
also the new edif.h EDIF management functions.
|
|
||||||
|
|
||||||
Revision 1.5 2002/04/30 04:26:42 steve
|
|
||||||
Spelling errors.
|
|
||||||
|
|
||||||
Revision 1.4 2001/09/16 22:26:47 steve
|
|
||||||
Support the cellref attribute.
|
|
||||||
|
|
||||||
Revision 1.3 2001/09/16 01:48:16 steve
|
|
||||||
Suppor the PAD attribute on signals.
|
|
||||||
|
|
||||||
Revision 1.2 2001/09/06 04:28:40 steve
|
|
||||||
Separate the virtex and generic-edif code generators.
|
|
||||||
|
|
||||||
Revision 1.1 2001/09/02 23:58:49 steve
|
|
||||||
Add documentation for the code generator.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -552,7 +552,7 @@ static void get_nexuses_from_expr(ivl_expr_t expr, set<ivl_nexus_t> &out)
|
||||||
/*
|
/*
|
||||||
* Attempt to identify common forms of wait statements and produce
|
* Attempt to identify common forms of wait statements and produce
|
||||||
* more idiomatic VHDL than would be produced by the generic
|
* more idiomatic VHDL than would be produced by the generic
|
||||||
* draw_wait funciton. The main application of this is a input to
|
* draw_wait function. The main application of this is a input to
|
||||||
* synthesis tools that don't synthesise the full VHDL language.
|
* synthesis tools that don't synthesise the full VHDL language.
|
||||||
* If none of these patterns are matched, the function returns false
|
* If none of these patterns are matched, the function returns false
|
||||||
* and the default draw_wait is used.
|
* and the default draw_wait is used.
|
||||||
|
|
|
||||||
|
|
@ -1853,7 +1853,7 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This little helper function generates the instructions to pad a
|
* This little helper function generates the instructions to pad a
|
||||||
* vector in place. It is assumed that the calling functio has set up
|
* vector in place. It is assumed that the calling function has set up
|
||||||
* the first sub_sidth bits of the dest vector, and the signed_flag is
|
* the first sub_sidth bits of the dest vector, and the signed_flag is
|
||||||
* true if the extension is to be signed.
|
* true if the extension is to be signed.
|
||||||
*/
|
*/
|
||||||
|
|
@ -2456,7 +2456,7 @@ static void draw_select_expr_dest(ivl_expr_t exp, struct vector_info dest,
|
||||||
|
|
||||||
/* If the shift expression is not present, then this is really
|
/* If the shift expression is not present, then this is really
|
||||||
a pad expression, and that can be handled pretty
|
a pad expression, and that can be handled pretty
|
||||||
easily. Evalutate the subexpression into the destination,
|
easily. Evaluate the subexpression into the destination,
|
||||||
then pad in place. */
|
then pad in place. */
|
||||||
if (shift == 0) {
|
if (shift == 0) {
|
||||||
struct vector_info subv;
|
struct vector_info subv;
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@
|
||||||
#
|
#
|
||||||
Summary: Icarus Verilog
|
Summary: Icarus Verilog
|
||||||
Name: verilog%{suff}
|
Name: verilog%{suff}
|
||||||
Version: 0.9.0.%{rev_date}
|
Version: 0.9.1
|
||||||
Release: 0
|
Release: 0
|
||||||
License: GPL
|
License: GPL
|
||||||
Group: Productivity/Scientific/Electronics
|
Group: Productivity/Scientific/Electronics
|
||||||
Source: verilog%{suff}-%{rev_date}.tar.gz
|
Source: verilog%{suff}-%{version}.tar.gz
|
||||||
URL: http://www.icarus.com/eda/verilog/index.html
|
URL: http://www.icarus.com/eda/verilog/index.html
|
||||||
Packager: Stephen Williams <steve@icarus.com>
|
Packager: Stephen Williams <steve@icarus.com>
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ engineering formats, including simulation. It strives to be true
|
||||||
to the IEEE-1364 standard.
|
to the IEEE-1364 standard.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -n verilog%{suff}-%{rev_date}
|
%setup -n verilog%{suff}-%{version}
|
||||||
|
|
||||||
%build
|
%build
|
||||||
if test X%{suff} != X
|
if test X%{suff} != X
|
||||||
|
|
|
||||||
41
verinum.cc
41
verinum.cc
|
|
@ -419,6 +419,7 @@ uint64_t verinum::as_ulong64() const
|
||||||
*/
|
*/
|
||||||
signed long verinum::as_long() const
|
signed long verinum::as_long() const
|
||||||
{
|
{
|
||||||
|
#define IVLLBITS (8 * sizeof(long) - 1)
|
||||||
if (nbits_ == 0)
|
if (nbits_ == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -426,33 +427,43 @@ signed long verinum::as_long() const
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
signed long val = 0;
|
signed long val = 0;
|
||||||
|
unsigned diag_top = 0;
|
||||||
|
|
||||||
|
unsigned top = nbits_;
|
||||||
|
if (top > IVLLBITS) {
|
||||||
|
diag_top = top;
|
||||||
|
top = IVLLBITS;
|
||||||
|
}
|
||||||
|
int lost_bits=0;
|
||||||
|
|
||||||
if (has_sign_ && (bits_[nbits_-1] == V1)) {
|
if (has_sign_ && (bits_[nbits_-1] == V1)) {
|
||||||
unsigned top = nbits_;
|
|
||||||
if (top > (8 * sizeof(long) - 1))
|
|
||||||
top = 8 * sizeof(long) - 1;
|
|
||||||
|
|
||||||
val = -1;
|
val = -1;
|
||||||
signed long mask = ~1L;
|
signed long mask = ~1L;
|
||||||
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
||||||
if (bits_[idx] == V0)
|
if (bits_[idx] == V0) val &= mask;
|
||||||
val &= mask;
|
|
||||||
|
|
||||||
mask = (mask << 1) | 1L;
|
mask = (mask << 1) | 1L;
|
||||||
}
|
}
|
||||||
|
if (diag_top) {
|
||||||
|
for (unsigned idx = top; idx < diag_top; idx += 1) {
|
||||||
|
if (bits_[idx] == V0) lost_bits=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned top = nbits_;
|
|
||||||
if (top > (8 * sizeof(long) - 1))
|
|
||||||
top = 8 * sizeof(long) - 1;
|
|
||||||
|
|
||||||
signed long mask = 1;
|
signed long mask = 1;
|
||||||
for (unsigned idx = 0 ; idx < top ; idx += 1, mask <<= 1)
|
for (unsigned idx = 0 ; idx < top ; idx += 1, mask <<= 1) {
|
||||||
if (bits_[idx] == V1)
|
if (bits_[idx] == V1) val |= mask;
|
||||||
val |= mask;
|
}
|
||||||
|
if (diag_top) {
|
||||||
|
for (unsigned idx = top; idx < diag_top; idx += 1) {
|
||||||
|
if (bits_[idx] == V1) lost_bits=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lost_bits) cerr << "warning: verinum::as_long() truncated " <<
|
||||||
|
diag_top << " bits to " << IVLLBITS << ", returns " << val << endl;
|
||||||
return val;
|
return val;
|
||||||
|
#undef IVLLBITS
|
||||||
}
|
}
|
||||||
|
|
||||||
double verinum::as_double() const
|
double verinum::as_double() const
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,5 @@
|
||||||
* Edit this definition in version_base.in to define the base version
|
* Edit this definition in version_base.in to define the base version
|
||||||
* number for the compiled result.
|
* number for the compiled result.
|
||||||
*/
|
*/
|
||||||
#define VERSION "0.9.devel"
|
#define VERSION "0.9.1"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
||||||
|
|
||||||
if (ld_zero == 1) {
|
if (ld_zero == 1) {
|
||||||
/* Strip the leading zeros if a width is not given. */
|
/* Strip the leading zeros if a width is not given. */
|
||||||
if (width == -1) while (*cp == '0') cp++;
|
if (width == -1) while (*cp == '0' && *(cp+1) != '\0') cp++;
|
||||||
/* Pad with leading zeros. */
|
/* Pad with leading zeros. */
|
||||||
else if (ljust == 0 && (signed)swidth < width) {
|
else if (ljust == 0 && (signed)swidth < width) {
|
||||||
unsigned pad = (unsigned)width - swidth;
|
unsigned pad = (unsigned)width - swidth;
|
||||||
|
|
@ -337,7 +337,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
||||||
strcpy(cp+pad, value.value.str);
|
strcpy(cp+pad, value.value.str);
|
||||||
free_flag = 1;
|
free_flag = 1;
|
||||||
/* For a left aligned value also strip the leading zeros. */
|
/* For a left aligned value also strip the leading zeros. */
|
||||||
} else if (ljust != 0) while (*cp == '0') cp++;
|
} else if (ljust != 0) while (*cp == '0' && *(cp+1) != '\0') cp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a width was not given, use a width of zero. */
|
/* If a width was not given, use a width of zero. */
|
||||||
|
|
|
||||||
|
|
@ -297,6 +297,8 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
|
||||||
|
|
||||||
static PLI_INT32 finish_cb(p_cb_data cause)
|
static PLI_INT32 finish_cb(p_cb_data cause)
|
||||||
{
|
{
|
||||||
|
struct vcd_info *cur, *next;
|
||||||
|
|
||||||
if (finish_status != 0) return 0;
|
if (finish_status != 0) return 0;
|
||||||
|
|
||||||
finish_status = 1;
|
finish_status = 1;
|
||||||
|
|
@ -306,6 +308,17 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
||||||
lt_set_time64(dump_file, dumpvars_time);
|
lt_set_time64(dump_file, dumpvars_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (cur = vcd_list ; cur ; cur = next) {
|
||||||
|
next = cur->next;
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
vcd_list = 0;
|
||||||
|
|
||||||
|
vcd_names_delete(&lxt_tab);
|
||||||
|
nexus_ident_delete();
|
||||||
|
free(dump_path);
|
||||||
|
dump_path = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -299,6 +299,8 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
|
||||||
|
|
||||||
static PLI_INT32 finish_cb(p_cb_data cause)
|
static PLI_INT32 finish_cb(p_cb_data cause)
|
||||||
{
|
{
|
||||||
|
struct vcd_info *cur, *next;
|
||||||
|
|
||||||
if (finish_status != 0) return 0;
|
if (finish_status != 0) return 0;
|
||||||
|
|
||||||
finish_status = 1;
|
finish_status = 1;
|
||||||
|
|
@ -308,6 +310,17 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
||||||
lxt2_wr_set_time64(dump_file, dumpvars_time);
|
lxt2_wr_set_time64(dump_file, dumpvars_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (cur = vcd_list ; cur ; cur = next) {
|
||||||
|
next = cur->next;
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
vcd_list = 0;
|
||||||
|
|
||||||
|
vcd_names_delete(&lxt_tab);
|
||||||
|
nexus_ident_delete();
|
||||||
|
free(dump_path);
|
||||||
|
dump_path = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,7 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
||||||
free((char *)cur->ident);
|
free((char *)cur->ident);
|
||||||
free(cur);
|
free(cur);
|
||||||
}
|
}
|
||||||
|
vcd_list = 0;
|
||||||
vcd_names_delete(&vcd_tab);
|
vcd_names_delete(&vcd_tab);
|
||||||
vcd_names_delete(&vcd_var);
|
vcd_names_delete(&vcd_var);
|
||||||
nexus_ident_delete();
|
nexus_ident_delete();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* $Id: README.txt,v 1.82 2007/03/22 16:08:19 steve Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VVP SIMULATION ENGINE
|
VVP SIMULATION ENGINE
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
# undef HAVE_NAN
|
# undef HAVE_NAN
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define this is you want to compile vvp with memory freeing and
|
* Define this if you want to compile vvp with memory freeing and
|
||||||
* special valgrind hooks for the memory pools.
|
* special valgrind hooks for the memory pools.
|
||||||
*/
|
*/
|
||||||
# undef CHECK_WITH_VALGRIND
|
# undef CHECK_WITH_VALGRIND
|
||||||
|
|
@ -68,29 +68,55 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
/* This is needed in C++ to get the PRI?64 formats. */
|
||||||
|
# ifndef __STDC_FORMAT_MACROS
|
||||||
|
# define __STDC_FORMAT_MACROS
|
||||||
|
# endif
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
#endif
|
|
||||||
|
typedef uint64_t vvp_time64_t;
|
||||||
|
|
||||||
|
# define TIME_FMT_O PRIo64
|
||||||
|
# define TIME_FMT_U PRIu64
|
||||||
|
# define TIME_FMT_X PRIx64
|
||||||
|
|
||||||
|
# if SIZEOF_UNSIGNED_LONG == 8
|
||||||
|
# define UL_AND_TIME64_SAME
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else /* HAVE_INTTYPES_H */
|
||||||
|
|
||||||
|
|
||||||
#if SIZEOF_UNSIGNED >= 8
|
#if SIZEOF_UNSIGNED >= 8
|
||||||
typedef unsigned vvp_time64_t;
|
typedef unsigned vvp_time64_t;
|
||||||
# define TIME_FMT ""
|
# define TIME_FMT_O "o"
|
||||||
|
# define TIME_FMT_U "u"
|
||||||
|
# define TIME_FMT_X "x"
|
||||||
#else
|
#else
|
||||||
# if SIZEOF_UNSIGNED_LONG >= 8
|
# if SIZEOF_UNSIGNED_LONG >= 8
|
||||||
typedef unsigned long vvp_time64_t;
|
typedef unsigned long vvp_time64_t;
|
||||||
# define UL_AND_TIME64_SAME
|
# define UL_AND_TIME64_SAME
|
||||||
# define TIME_FMT "l"
|
# define TIME_FMT_O "lo"
|
||||||
|
# define TIME_FMT_U "lu"
|
||||||
|
# define TIME_FMT_X "lx"
|
||||||
# else
|
# else
|
||||||
# if SIZEOF_UNSIGNED_LONG_LONG > SIZEOF_UNSIGNED_LONG
|
# if SIZEOF_UNSIGNED_LONG_LONG > SIZEOF_UNSIGNED_LONG
|
||||||
typedef unsigned long long vvp_time64_t;
|
typedef unsigned long long vvp_time64_t;
|
||||||
# define TIME_FMT "ll"
|
# define TIME_FMT_O "llo"
|
||||||
|
# define TIME_FMT_U "llu"
|
||||||
|
# define TIME_FMT_X "llx"
|
||||||
# else
|
# else
|
||||||
typedef unsigned long vvp_time64_t;
|
typedef unsigned long vvp_time64_t;
|
||||||
# define UL_AND_TIME64_SAME
|
# define UL_AND_TIME64_SAME
|
||||||
# define TIME_FMT "l"
|
# define TIME_FMT_O "lo"
|
||||||
|
# define TIME_FMT_U "lu"
|
||||||
|
# define TIME_FMT_X "lx"
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAVE_INTTYPES_H */
|
||||||
|
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
|
|
||||||
/* getrusage, /proc/self/statm */
|
/* getrusage, /proc/self/statm */
|
||||||
|
|
|
||||||
|
|
@ -483,7 +483,7 @@ void stop_handler(int rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
vpi_mcd_printf(1,"** VVP Stop(%d) **\n", rc);
|
vpi_mcd_printf(1,"** VVP Stop(%d) **\n", rc);
|
||||||
vpi_mcd_printf(1,"** Current simulation time is %" TIME_FMT "u ticks.\n",
|
vpi_mcd_printf(1,"** Current simulation time is %" TIME_FMT_U " ticks.\n",
|
||||||
schedule_simtime());
|
schedule_simtime());
|
||||||
|
|
||||||
interact_flag = true;
|
interact_flag = true;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* $Id: vpi.txt,v 1.8 2007/03/22 16:08:19 steve Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -265,17 +265,17 @@ static void timevar_get_value(vpiHandle ref, s_vpi_value*vp, bool is_int_func,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiDecStrVal:
|
case vpiDecStrVal:
|
||||||
sprintf(rbuf, "%" TIME_FMT "u", simtime);
|
sprintf(rbuf, "%" TIME_FMT_U, simtime);
|
||||||
vp->value.str = rbuf;
|
vp->value.str = rbuf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiOctStrVal:
|
case vpiOctStrVal:
|
||||||
sprintf(rbuf, "%" TIME_FMT "o", simtime);
|
sprintf(rbuf, "%" TIME_FMT_O, simtime);
|
||||||
vp->value.str = rbuf;
|
vp->value.str = rbuf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiHexStrVal:
|
case vpiHexStrVal:
|
||||||
sprintf(rbuf, "%" TIME_FMT "x", simtime);
|
sprintf(rbuf, "%" TIME_FMT_X, simtime);
|
||||||
vp->value.str = rbuf;
|
vp->value.str = rbuf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1974,7 +1974,8 @@ static unsigned long divide2words(unsigned long a, unsigned long b,
|
||||||
|
|
||||||
static unsigned long* divide_bits(unsigned long*ap, unsigned long*bp, unsigned wid)
|
static unsigned long* divide_bits(unsigned long*ap, unsigned long*bp, unsigned wid)
|
||||||
{
|
{
|
||||||
|
// Do all our work a cpu-word at a time. The "words" variable
|
||||||
|
// is the number of words of the wid.
|
||||||
unsigned words = (wid+CPU_WORD_BITS-1) / CPU_WORD_BITS;
|
unsigned words = (wid+CPU_WORD_BITS-1) / CPU_WORD_BITS;
|
||||||
|
|
||||||
unsigned btop = words-1;
|
unsigned btop = words-1;
|
||||||
|
|
@ -1985,6 +1986,8 @@ static unsigned long* divide_bits(unsigned long*ap, unsigned long*bp, unsigned w
|
||||||
if (btop==0 && bp[0]==0)
|
if (btop==0 && bp[0]==0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// The result array will eventually accumulate the result. The
|
||||||
|
// diff array is a difference that we use in the intermediate.
|
||||||
unsigned long*diff = new unsigned long[words];
|
unsigned long*diff = new unsigned long[words];
|
||||||
unsigned long*result= new unsigned long[words];
|
unsigned long*result= new unsigned long[words];
|
||||||
for (unsigned idx = 0 ; idx < words ; idx += 1)
|
for (unsigned idx = 0 ; idx < words ; idx += 1)
|
||||||
|
|
@ -2012,10 +2015,11 @@ static unsigned long* divide_bits(unsigned long*ap, unsigned long*bp, unsigned w
|
||||||
|
|
||||||
// cur_res is a guestimate of the result this far. It
|
// cur_res is a guestimate of the result this far. It
|
||||||
// may be 1 too big. (But it will also be >0) Try it,
|
// may be 1 too big. (But it will also be >0) Try it,
|
||||||
// and if the difference comes out negative, then adjust
|
// and if the difference comes out negative, then adjust.
|
||||||
// then.
|
|
||||||
|
|
||||||
|
// diff = (bp * cur_res) << cur_ptr;
|
||||||
multiply_array_imm(diff+cur_ptr, bp, words-cur_ptr, cur_res);
|
multiply_array_imm(diff+cur_ptr, bp, words-cur_ptr, cur_res);
|
||||||
|
// ap -= diff
|
||||||
unsigned long carry = 1;
|
unsigned long carry = 1;
|
||||||
for (unsigned idx = cur_ptr ; idx < words ; idx += 1)
|
for (unsigned idx = cur_ptr ; idx < words ; idx += 1)
|
||||||
ap[idx] = add_with_carry(ap[idx], ~diff[idx], carry);
|
ap[idx] = add_with_carry(ap[idx], ~diff[idx], carry);
|
||||||
|
|
@ -2027,12 +2031,14 @@ static unsigned long* divide_bits(unsigned long*ap, unsigned long*bp, unsigned w
|
||||||
// case, we know that cur_res was too large by 1. Correct by
|
// case, we know that cur_res was too large by 1. Correct by
|
||||||
// adding 1b back in and reducing cur_res.
|
// adding 1b back in and reducing cur_res.
|
||||||
if ((carry&1) == 0) {
|
if ((carry&1) == 0) {
|
||||||
cur_res -= 1;
|
// Keep adding b back in until the remainder
|
||||||
carry = 0;
|
// becomes positive again.
|
||||||
for (unsigned idx = cur_ptr ; idx < words ; idx += 1)
|
do {
|
||||||
ap[idx] = add_with_carry(ap[idx], bp[idx-cur_ptr], carry);
|
cur_res -= 1;
|
||||||
// The sign *must* have changed again.
|
carry = 0;
|
||||||
assert(carry == 1);
|
for (unsigned idx = cur_ptr ; idx < words ; idx += 1)
|
||||||
|
ap[idx] = add_with_carry(ap[idx], bp[idx-cur_ptr], carry);
|
||||||
|
} while (carry == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
result[cur_ptr] = cur_res;
|
result[cur_ptr] = cur_res;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* $Id: vthread.txt,v 1.6 2005/09/19 21:45:37 steve Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3399,7 +3399,7 @@ ostream& operator <<(ostream&out, vvp_scalar_t a)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is only called if the actual interface function rules
|
* This function is only called if the actual interface function rules
|
||||||
* out some of the eazy cases. If we get here, we can assume that
|
* out some of the easy cases. If we get here, we can assume that
|
||||||
* neither of the values is HiZ, and the values are not exactly equal.
|
* neither of the values is HiZ, and the values are not exactly equal.
|
||||||
*/
|
*/
|
||||||
vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b)
|
vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue