Merge branch 'master' into vec4-stack
Conflicts: elab_lval.cc
This commit is contained in:
commit
1d63875e5d
|
|
@ -38,7 +38,7 @@ srcdir = @srcdir@
|
|||
datarootdir = @datarootdir@
|
||||
|
||||
SUBDIRS = ivlpp vhdlpp vvp vpi libveriuser cadpli tgt-null tgt-stub tgt-vvp \
|
||||
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif driver
|
||||
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer driver
|
||||
# Only run distclean for these directories.
|
||||
NOTUSED = tgt-fpga tgt-pal tgt-verilog
|
||||
|
||||
|
|
|
|||
|
|
@ -325,4 +325,4 @@ AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
|
|||
fi
|
||||
AC_MSG_RESULT(ok)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile)
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile)
|
||||
|
|
|
|||
88
elab_lval.cc
88
elab_lval.cc
|
|
@ -301,7 +301,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. Wires are not allowed in this context,
|
||||
unless this is the l-value of a force. */
|
||||
if ((reg->type() != NetNet::REG) && !is_force) {
|
||||
if ((reg->type() != NetNet::REG)
|
||||
&& (reg->type() != NetNet::UNRESOLVED_WIRE)
|
||||
&& !is_force) {
|
||||
cerr << get_fileline() << ": error: " << path_ <<
|
||||
" is not a valid l-value in " << scope_path(use_scope) <<
|
||||
"." << endl;
|
||||
|
|
@ -326,7 +328,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
// where the name is a member/method of a struct/class.
|
||||
ivl_assert(*this, method_name.nil());
|
||||
|
||||
bool need_const_idx = is_cassign || is_force;
|
||||
bool need_const_idx = is_cassign || is_force || (reg->type()==NetNet::UNRESOLVED_WIRE);
|
||||
|
||||
if (reg->unpacked_dimensions() > 0)
|
||||
return elaborate_lval_net_word_(des, scope, reg, need_const_idx);
|
||||
|
|
@ -370,6 +372,14 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
|
||||
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE && !is_force) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< path_ << " Unable to assign to unresolved wires."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No select expressions. */
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
|
|
@ -531,6 +541,13 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
|||
<< "canon_index=" << *canon_index << endl;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Unable to assign words of unresolved wire array." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
lv->set_word(canon_index);
|
||||
|
||||
|
|
@ -623,6 +640,19 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate && (reg->type()==NetNet::UNRESOLVED_WIRE)) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_bit_: "
|
||||
<< "Try to assign bits of unresolved wire."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Notice that we might be assigning to an unresolved wire. This
|
||||
// can happen if we are actually assigning to a variable that
|
||||
// has a partial continuous assignment to it. If that is the
|
||||
// case, then the bit select must be constant.
|
||||
ivl_assert(*this, need_const_idx || (reg->type()!=NetNet::UNRESOLVED_WIRE));
|
||||
|
||||
|
||||
if (prefix_indices.size()+2 <= reg->packed_dims().size()) {
|
||||
// Special case: this is a slice of a multi-dimensional
|
||||
// packed array. For example:
|
||||
|
|
@ -637,8 +667,19 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||
ivl_assert(*this, rcl);
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
bool rct = reg->test_and_set_part_driver(loff+lwid-1, loff);
|
||||
if (rct) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "These bits are already driven." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), lwid);
|
||||
|
||||
} else {
|
||||
ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE);
|
||||
unsigned long lwid;
|
||||
mux = normalize_variable_slice_base(prefix_indices, mux,
|
||||
reg, lwid);
|
||||
|
|
@ -646,6 +687,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
}
|
||||
|
||||
} else if (reg->data_type() == IVL_VT_STRING) {
|
||||
ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE);
|
||||
// Special case: This is a select of a string
|
||||
// variable. The target of the assignment is a character
|
||||
// select of a string. Force the r-value to be an 8bit
|
||||
|
|
@ -662,6 +704,8 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
lv->set_part(new NetEConst(verinum(lsb)), 8);
|
||||
|
||||
} else if (mux) {
|
||||
ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE);
|
||||
|
||||
// Non-constant bit mux. Correct the mux for the range
|
||||
// of the vector, then set the l-value part select
|
||||
// expression.
|
||||
|
|
@ -679,6 +723,10 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
// Constant bit mux that happens to select the only bit
|
||||
// of the l-value. Don't bother with any select at all.
|
||||
|
||||
// NOTE: Don't know what to do about unresolved wires
|
||||
// here, but they are probably wrong.
|
||||
ivl_assert(*this, reg->type()!=NetNet::UNRESOLVED_WIRE);
|
||||
|
||||
} else {
|
||||
// Constant bit select that does something useful.
|
||||
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||
|
|
@ -691,6 +739,15 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
bool rct = reg->test_and_set_part_driver(loff, loff);
|
||||
if (rct) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Bit " << loff << " is already driven." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), 1);
|
||||
}
|
||||
|
||||
|
|
@ -705,6 +762,14 @@ bool PEIdent::elaborate_lval_darray_bit_(Design*des, NetScope*scope, NetAssign_*
|
|||
// For now, only support single-dimension dynamic arrays.
|
||||
ivl_assert(*this, name_tail.index.size() == 1);
|
||||
|
||||
if (lv->sig()->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< path_ << " Unable to darray word select unresolved wires."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
|
@ -747,6 +812,17 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
bool rct = reg->test_and_set_part_driver(msb, lsb);
|
||||
if (rct) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< path_ << "Part select is double-driving unresolved wire."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const vector<netrange_t>&packed = reg->packed_dims();
|
||||
|
||||
long loff, moff;
|
||||
|
|
@ -1127,6 +1203,14 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
|||
packed_base = 0;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< path_ << " Unable to member-select unresolved wires."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (packed_base == 0) {
|
||||
lv->set_part(new NetEConst(verinum(off)), use_width);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -710,7 +710,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
unsigned subnet_wid = midx-lidx+1;
|
||||
|
||||
/* Check if the l-value bits are double-driven. */
|
||||
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_part_lref(midx,lidx)) {
|
||||
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx)) {
|
||||
cerr << get_fileline() << ": error: Unresolved net/uwire "
|
||||
<< sig->name() << " cannot have multiple drivers." << endl;
|
||||
des->errors += 1;
|
||||
|
|
|
|||
|
|
@ -868,7 +868,7 @@ unsigned NetNet::peek_eref() const
|
|||
* Test each of the bits in the range, and set them. If any bits are
|
||||
* already set then return true.
|
||||
*/
|
||||
bool NetNet::test_part_lref(unsigned pmsb, unsigned plsb)
|
||||
bool NetNet::test_and_set_part_driver(unsigned pmsb, unsigned plsb)
|
||||
{
|
||||
if (lref_mask_.empty())
|
||||
lref_mask_.resize(vector_width());
|
||||
|
|
|
|||
13
netlist.h
13
netlist.h
|
|
@ -726,17 +726,22 @@ class NetNet : public NetObj, public PortType {
|
|||
bool local_flag() const { return local_flag_; }
|
||||
void local_flag(bool f) { local_flag_ = f; }
|
||||
|
||||
/* NetESignal objects may reference this object. Keep a
|
||||
reference count so that I keep track of them. */
|
||||
// NetESignal objects may reference this object. Keep a
|
||||
// reference count so that I keep track of them.
|
||||
void incr_eref();
|
||||
void decr_eref();
|
||||
unsigned peek_eref() const;
|
||||
|
||||
/* Assignment statements count their lrefs here. */
|
||||
// Assignment statements count their lrefs here. And by
|
||||
// asignment statements, we mean BEHAVIORAL assignments.
|
||||
void incr_lref();
|
||||
void decr_lref();
|
||||
unsigned peek_lref() const { return lref_count_; }
|
||||
bool test_part_lref(unsigned msb, unsigned lsb);
|
||||
|
||||
// Treating this node as a uwire, this function tests whether
|
||||
// any bits in the canonical part are already driven. This is
|
||||
// only useful for UNRESOLVED_WIRE objects.
|
||||
bool test_and_set_part_driver(unsigned msb, unsigned lsb);
|
||||
|
||||
unsigned get_refs() const;
|
||||
|
||||
|
|
|
|||
7
parse.y
7
parse.y
|
|
@ -3853,8 +3853,15 @@ port_declaration
|
|||
use_type = NetNet::IMPLICIT;
|
||||
else
|
||||
use_type = NetNet::IMPLICIT_REG;
|
||||
|
||||
// The SystemVerilog types that can show up as
|
||||
// output ports are implicitly (on the inside)
|
||||
// variables because "reg" is not valid syntax
|
||||
// here.
|
||||
} else if (dynamic_cast<atom2_type_t*> ($4)) {
|
||||
use_type = NetNet::IMPLICIT_REG;
|
||||
} else if (dynamic_cast<struct_type_t*> ($4)) {
|
||||
use_type = NetNet::IMPLICIT_REG;
|
||||
}
|
||||
}
|
||||
ptmp = pform_module_port_reference(name, @2.text, @2.first_line);
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ struct symbol_search_results {
|
|||
NetEvent*eve;
|
||||
};
|
||||
|
||||
bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
pform_name_t path, struct symbol_search_results*res,
|
||||
NetScope*start_scope = 0)
|
||||
static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
pform_name_t path, struct symbol_search_results*res,
|
||||
NetScope*start_scope = 0)
|
||||
{
|
||||
assert(scope);
|
||||
bool prefix_scope = false;
|
||||
|
|
@ -100,6 +100,9 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
|||
"`" << path_tail.name << "' in path `" << path << "'" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
} else {
|
||||
// Prefix is present, but is NOT a scope. Fail!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
118
synth2.cc
118
synth2.cc
|
|
@ -189,18 +189,18 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
unsigned sel_width = esig->vector_width();
|
||||
assert(sel_width > 0);
|
||||
|
||||
unsigned mux_width = 0;
|
||||
for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1)
|
||||
mux_width += nex_out.pin(idx).nexus()->vector_width();
|
||||
ivl_assert(*this, nex_map.size() == nex_out.pin_count());
|
||||
|
||||
unsigned map_width = 0;
|
||||
for (unsigned idx = 0 ; idx < nex_map.size() ; idx += 1)
|
||||
map_width += nex_map[idx].wid;
|
||||
vector<unsigned> mux_width (nex_out.pin_count());
|
||||
for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) {
|
||||
mux_width[idx] = nex_map[idx].wid;
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCase::synth_async: "
|
||||
<< "idx=" << idx
|
||||
<< ", mux_width[idx]=" << mux_width[idx] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the mux width from the map, the mex_map values
|
||||
are from the top level and are more reliable. */
|
||||
if (map_width > mux_width)
|
||||
mux_width = map_width;
|
||||
|
||||
/* Collect all the statements into a map of index to
|
||||
statement. The guard expression it evaluated to be the
|
||||
|
|
@ -230,6 +230,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
max_guard_value = sel_idx;
|
||||
}
|
||||
|
||||
// The mux_size is the number of inputs that are selected.
|
||||
unsigned mux_size = max_guard_value + 1;
|
||||
|
||||
// If the sel_width can select more than just the explicit
|
||||
|
|
@ -240,48 +241,59 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
mux_width, mux_size, sel_width);
|
||||
des->add_node(mux);
|
||||
|
||||
/* The select signal is already synthesized. Simply hook it up. */
|
||||
connect(mux->pin_Sel(), esig->pin(0));
|
||||
|
||||
/* For now, assume that the output is only 1 signal. */
|
||||
ivl_assert(*this, nex_out.pin_count() == 1);
|
||||
connect(mux->pin_Result(), nex_out.pin(0));
|
||||
|
||||
/* Make sure the output is already connected to a net. */
|
||||
if (mux->pin_Result().nexus()->pick_any_net() == 0) {
|
||||
ivl_variable_type_t mux_data_type = IVL_VT_LOGIC;
|
||||
netvector_t*tmp_vec = new netvector_t(mux_data_type, mux_width-1, 0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, tmp_vec);
|
||||
tmp->local_flag(true);
|
||||
ivl_assert(*this, tmp->vector_width() != 0);
|
||||
connect(mux->pin_Result(), tmp->pin(0));
|
||||
}
|
||||
|
||||
/* If there is a default clause, synthesize is once and we'll
|
||||
link it in wherever it is needed. */
|
||||
NetNet*default_sig = 0;
|
||||
NetBus default_bus (scope, nex_map.size());
|
||||
vector<NetNet*>default_sig (nex_map.size());
|
||||
|
||||
if (statement_default) {
|
||||
|
||||
NetBus tmp (scope, nex_map.size());
|
||||
statement_default->synth_async(des, scope, nex_map, tmp);
|
||||
statement_default->synth_async(des, scope, nex_map, default_bus);
|
||||
|
||||
// Get the signal from the synthesized statement. This
|
||||
// will be hooked to all the default cases.
|
||||
ivl_assert(*this, tmp.pin_count()==1);
|
||||
default_sig = tmp.pin(0).nexus()->pick_any_net();
|
||||
ivl_assert(*this, default_sig);
|
||||
ivl_assert(*this, default_bus.pin_count()==1);
|
||||
default_sig[0] = default_bus.pin(0).nexus()->pick_any_net();
|
||||
ivl_assert(*this, default_sig[0]);
|
||||
}
|
||||
|
||||
vector<NetMux*> mux (mux_width.size());
|
||||
for (size_t mdx = 0 ; mdx < mux_width.size() ; mdx += 1) {
|
||||
mux[mdx] = new NetMux(scope, scope->local_symbol(),
|
||||
mux_width[mdx], mux_size, sel_width);
|
||||
des->add_node(mux[mdx]);
|
||||
|
||||
// The select signal is already synthesized, and is
|
||||
// common for every mux of this case statement. Simply
|
||||
// hook it up.
|
||||
connect(mux[mdx]->pin_Sel(), esig->pin(0));
|
||||
|
||||
// The outputs are in the nex_out, and connected to the
|
||||
// mux Result pins.
|
||||
connect(mux[mdx]->pin_Result(), nex_out.pin(mdx));
|
||||
|
||||
// Make sure the output is now connected to a net. If
|
||||
// not, then create a fake one to carry the net-ness of
|
||||
// the pin.
|
||||
if (mux[mdx]->pin_Result().nexus()->pick_any_net() == 0) {
|
||||
ivl_variable_type_t mux_data_type = IVL_VT_LOGIC;
|
||||
netvector_t*tmp_vec = new netvector_t(mux_data_type, mux_width[mdx]-1, 0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, tmp_vec);
|
||||
tmp->local_flag(true);
|
||||
ivl_assert(*this, tmp->vector_width() != 0);
|
||||
connect(mux[mdx]->pin_Result(), tmp->pin(0));
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < mux_size ; idx += 1) {
|
||||
|
||||
NetProc*stmt = statement_map[idx];
|
||||
if (stmt==0 && default_sig!=0) {
|
||||
connect(mux->pin_Data(idx), default_sig->pin(0));
|
||||
if (stmt==0 && statement_default) {
|
||||
ivl_assert(*this, default_sig.size() == mux.size());
|
||||
for (size_t mdx = 0 ; mdx < mux.size() ; mdx += 1)
|
||||
connect(mux[mdx]->pin_Data(idx), default_sig[mdx]->pin(0));
|
||||
|
||||
continue;
|
||||
}
|
||||
if (stmt == 0) {
|
||||
|
|
@ -294,9 +306,24 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
NetBus tmp (scope, nex_map.size());
|
||||
stmt->synth_async(des, scope, nex_map, tmp);
|
||||
|
||||
ivl_assert(*this, tmp.pin_count()==1);
|
||||
connect(mux->pin_Data(idx), tmp.pin(0));
|
||||
ivl_assert(*this, mux->pin_Data(idx).nexus()->pick_any_net());
|
||||
ivl_assert(*this, tmp.pin_count() == mux.size());
|
||||
for (size_t mdx = 0 ; mdx < mux.size() ; mdx += 1) {
|
||||
connect(mux[mdx]->pin_Data(idx), tmp.pin(mdx));
|
||||
|
||||
if (mux[mdx]->pin_Data(idx).nexus()->pick_any_net()==0) {
|
||||
cerr << get_fileline() << ": warning: case " << idx
|
||||
<< " has no input for mux " << mdx << "." << endl;
|
||||
|
||||
ivl_variable_type_t mux_data_type = IVL_VT_LOGIC;
|
||||
netvector_t*tmp_vec = new netvector_t(mux_data_type, mux_width[mdx]-1, 0);
|
||||
NetNet*tmpn = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, tmp_vec);
|
||||
tmpn->local_flag(true);
|
||||
ivl_assert(*this, tmpn->vector_width() != 0);
|
||||
connect(mux[mdx]->pin_Data(idx), tmpn->pin(0));
|
||||
}
|
||||
ivl_assert(*this, mux[mdx]->pin_Data(idx).nexus()->pick_any_net());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -842,15 +869,16 @@ bool NetProcTop::synth_sync(Design*des)
|
|||
|
||||
for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) {
|
||||
|
||||
ivl_assert(*this, nex_set[idx].nex);
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Top level making a "
|
||||
<< nex_set[idx].nex->vector_width() << "-wide "
|
||||
<< nex_set[idx].wid << "-wide "
|
||||
<< "NetFF device." << endl;
|
||||
}
|
||||
|
||||
NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(),
|
||||
nex_set[idx].nex->vector_width());
|
||||
nex_set[idx].wid);
|
||||
des->add_node(ff2);
|
||||
ff2->set_line(*this);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
|
||||
CXX = @CXX@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
ifeq (@srcdir@,.)
|
||||
INCLUDE_PATH = -I. -I..
|
||||
else
|
||||
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = sizer.o scan_lpms.o scan_logs.o
|
||||
|
||||
all: dep sizer.tgt
|
||||
|
||||
check: all
|
||||
|
||||
clean:
|
||||
rm -rf *.o dep sizer.tgt
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.log
|
||||
|
||||
cppcheck: $(O:.o=.cc)
|
||||
cppcheck --enable=all -f $(INCLUDE_PATH) $^
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd ..; ./config.status --file=tgt-sizer/$@
|
||||
|
||||
dep:
|
||||
mkdir dep
|
||||
|
||||
%.o: %.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
TGTDEPLIBS=../libivl.a
|
||||
else
|
||||
TGTLDFLAGS=
|
||||
TGTDEPLIBS=
|
||||
endif
|
||||
|
||||
sizer.tgt: $O $(TGTDEPLIBS)
|
||||
$(CXX) @shared@ $(LDFLAGS) -o $@ $O $(TGTLDFLAGS)
|
||||
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/sizer.tgt $(INSTALL_DOC) $(libdir)/ivl$(suffix)/sizer.conf $(libdir)/ivl$(suffix)/sizer-s.conf
|
||||
|
||||
$(libdir)/ivl$(suffix)/sizer.tgt: ./sizer.tgt
|
||||
$(INSTALL_PROGRAM) ./sizer.tgt "$(DESTDIR)$(libdir)/ivl$(suffix)/sizer.tgt"
|
||||
|
||||
$(libdir)/ivl$(suffix)/sizer.conf: $(srcdir)/sizer.conf
|
||||
$(INSTALL_DATA) $(srcdir)/sizer.conf "$(DESTDIR)$(libdir)/ivl$(suffix)/sizer.conf"
|
||||
|
||||
$(libdir)/ivl$(suffix)/sizer-s.conf: $(srcdir)/sizer-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/sizer-s.conf "$(DESTDIR)$(libdir)/ivl$(suffix)/sizer-s.conf"
|
||||
|
||||
|
||||
installdirs: $(srcdir)/../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)/ivl$(suffix)"
|
||||
|
||||
uninstall:
|
||||
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/sizer.tgt"
|
||||
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/sizer.conf"
|
||||
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/sizer-s.conf"
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
# include "sizer_priv.h"
|
||||
|
||||
void scan_logs_gates(ivl_scope_t, ivl_net_logic_t log, struct sizer_statistics&stats)
|
||||
{
|
||||
unsigned wid = ivl_logic_width(log);
|
||||
|
||||
stats.gate_count += wid;
|
||||
}
|
||||
|
||||
void scan_logs(ivl_scope_t scope, struct sizer_statistics&stats)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < ivl_scope_logs(scope) ; idx += 1) {
|
||||
ivl_net_logic_t log = ivl_scope_log(scope, idx);
|
||||
switch (ivl_logic_type(log)) {
|
||||
case IVL_LO_AND:
|
||||
case IVL_LO_OR:
|
||||
case IVL_LO_XOR:
|
||||
case IVL_LO_NAND:
|
||||
case IVL_LO_NOR:
|
||||
case IVL_LO_XNOR:
|
||||
case IVL_LO_BUF:
|
||||
case IVL_LO_NOT:
|
||||
scan_logs_gates(scope, log, stats);
|
||||
break;
|
||||
default:
|
||||
stats.log_bytype[ivl_logic_type(log)] += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "sizer_priv.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Count each bit of flip-flops. It is clear and obvious how these
|
||||
* come out, so no need to make alternate counts as well.
|
||||
*/
|
||||
static void scan_lpms_ff(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats)
|
||||
{
|
||||
ivl_nexus_t out = ivl_lpm_q(lpm);
|
||||
unsigned wid = get_nexus_width(out);
|
||||
|
||||
stats.flop_count += wid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Count adders as 2m gates.
|
||||
* Also keep a count of adders by width, just out of curiosity.
|
||||
*/
|
||||
static void scans_lpms_add(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats)
|
||||
{
|
||||
unsigned wid = ivl_lpm_width(lpm);
|
||||
|
||||
stats.adder_count[wid] += 1;
|
||||
|
||||
stats.gate_count += 2*wid;
|
||||
}
|
||||
|
||||
void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < ivl_scope_lpms(scope) ; idx += 1) {
|
||||
ivl_lpm_t lpm = ivl_scope_lpm(scope,idx);
|
||||
switch (ivl_lpm_type(lpm)) {
|
||||
// Part select nodes don't actually take up
|
||||
// hardware. These represent things like bundle
|
||||
// manipulations, which are done in routing.
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
case IVL_LPM_CONCAT:
|
||||
case IVL_LPM_CONCATZ:
|
||||
case IVL_LPM_REPEAT:
|
||||
break;
|
||||
|
||||
case IVL_LPM_ADD:
|
||||
scans_lpms_add(scope, lpm, stats);
|
||||
break;
|
||||
|
||||
// D-Type flip-flops.
|
||||
case IVL_LPM_FF:
|
||||
scan_lpms_ff(scope, lpm, stats);
|
||||
break;
|
||||
|
||||
default:
|
||||
stats.lpm_bytype[ivl_lpm_type(lpm)] += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
flag:DLL=sizer.tgt
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "version_base.h"
|
||||
# include "version_tag.h"
|
||||
# include "config.h"
|
||||
# include "sizer_priv.h"
|
||||
# include <cstdio>
|
||||
# include <cstring>
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* This is a null target module. It does nothing.
|
||||
*/
|
||||
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog SIZER Statistics Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2014 Stephen Williams (steve@icarus.com)\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
" (at your option) any later version.\n"
|
||||
"\n"
|
||||
" This program is distributed in the hope that it will be useful,\n"
|
||||
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
" You should have received a copy of the GNU General Public License along\n"
|
||||
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
|
||||
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
|
||||
;
|
||||
|
||||
int sizer_errors = 0;
|
||||
|
||||
FILE*sizer_out = 0;
|
||||
|
||||
static int process_scan_fun(ivl_process_t net, void*raw);
|
||||
static void emit_sizer_scope(ivl_design_t des, ivl_scope_t model, struct sizer_statistics&stats);
|
||||
static void show_stats(struct sizer_statistics&stats);
|
||||
|
||||
/*
|
||||
* This is called by the ivl core to get version information from the
|
||||
* loadable code generator.
|
||||
*/
|
||||
const char* target_query(const char*key)
|
||||
{
|
||||
if (strcmp(key,"version") == 0)
|
||||
return version_string;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the main entry point from the IVL core.
|
||||
*/
|
||||
int target_design(ivl_design_t des)
|
||||
{
|
||||
const char*sizer_path = ivl_design_flag(des, "-o");
|
||||
|
||||
sizer_out = fopen(sizer_path, "wt");
|
||||
assert(sizer_out);
|
||||
|
||||
// Detect processes and dispatch them.
|
||||
ivl_design_process(des, &process_scan_fun, 0);
|
||||
|
||||
// Locate the root scopes for the design.
|
||||
ivl_scope_t*roots;
|
||||
unsigned nroots;
|
||||
ivl_design_roots(des, &roots, &nroots);
|
||||
|
||||
// Process all the root scopes. It is possible that there are
|
||||
// multiple root scopes, we will give isolated numbers for
|
||||
// each and keep then separate.
|
||||
for (unsigned idx = 0 ; idx < nroots ; idx += 1) {
|
||||
if (ivl_scope_type(roots[idx]) != IVL_SCT_MODULE) {
|
||||
fprintf(stderr, "SIZER: The root scope %s must be a module.\n", ivl_scope_basename(roots[idx]));
|
||||
sizer_errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
struct sizer_statistics stats;
|
||||
emit_sizer_scope(des, roots[idx], stats);
|
||||
|
||||
fprintf(sizer_out, "**** TOTALS\n");
|
||||
show_stats(stats);
|
||||
}
|
||||
|
||||
return sizer_errors;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Processes are not collected into scopes, but we should not have any
|
||||
* left anyhow. Give error messages for all the processes that we find
|
||||
* to be remaining.
|
||||
*/
|
||||
static int process_scan_fun(ivl_process_t net, void* /*raw*/)
|
||||
{
|
||||
fprintf(stderr, "%s:%u: SIZER: Processes not synthesized for statistics.\n",
|
||||
ivl_process_file(net), ivl_process_lineno(net));
|
||||
sizer_errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void emit_sizer_scope(ivl_design_t des, ivl_scope_t scope, struct sizer_statistics&stats)
|
||||
{
|
||||
fprintf(sizer_out, "**** module/scope: %s\n", ivl_scope_name(scope));
|
||||
|
||||
scan_logs(scope, stats);
|
||||
scan_lpms(scope, stats);
|
||||
|
||||
show_stats(stats);
|
||||
|
||||
for (size_t idx = 0 ; idx < ivl_scope_childs(scope) ; idx += 1) {
|
||||
ivl_scope_t child = ivl_scope_child(scope,idx);
|
||||
struct sizer_statistics child_stats;
|
||||
emit_sizer_scope(des, child, child_stats);
|
||||
stats += child_stats;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_stats(struct sizer_statistics&stats)
|
||||
{
|
||||
fprintf(sizer_out, " Flip-Flops : %u\n", stats.flop_count);
|
||||
fprintf(sizer_out, " Logic Gates : %u\n", stats.gate_count);
|
||||
|
||||
for (map<unsigned,unsigned>::const_iterator cur = stats.adder_count.begin()
|
||||
; cur != stats.adder_count.end() ; ++ cur) {
|
||||
fprintf(sizer_out, " ADDER[%u]: %u\n", cur->first, cur->second);
|
||||
}
|
||||
|
||||
// These are diagnostic outputs for when more detail is needed.
|
||||
for (map<ivl_lpm_type_t,unsigned>::const_iterator cur = stats.lpm_bytype.begin()
|
||||
; cur != stats.lpm_bytype.end() ; ++ cur) {
|
||||
fprintf(sizer_out, " LPM[%d]: %u unaccounted\n", cur->first, cur->second);
|
||||
}
|
||||
|
||||
for (map<ivl_logic_t,unsigned>::const_iterator cur = stats.log_bytype.begin()
|
||||
; cur != stats.log_bytype.end() ; ++ cur) {
|
||||
fprintf(sizer_out, " LOG[%d]: %u unaccounted\n", cur->first, cur->second);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_nexus_width(ivl_nexus_t nex)
|
||||
{
|
||||
ivl_signal_t sig = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex,idx);
|
||||
sig = ivl_nexus_ptr_sig(ptr);
|
||||
if (sig) return ivl_signal_width(sig);
|
||||
}
|
||||
|
||||
fprintf(stderr, "SIZER: Unable to find width of nexus?!\n");
|
||||
sizer_errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sizer_statistics& sizer_statistics::operator += (const sizer_statistics&that)
|
||||
{
|
||||
flop_count += that.flop_count;
|
||||
gate_count += that.gate_count;
|
||||
|
||||
for (map<unsigned,unsigned>::const_iterator cur = that.adder_count.begin()
|
||||
; cur != that.adder_count.end() ; ++ cur)
|
||||
adder_count[cur->first] += cur->second;
|
||||
|
||||
|
||||
for (map<ivl_lpm_type_t,unsigned>::const_iterator cur = that.lpm_bytype.begin()
|
||||
; cur != that.lpm_bytype.end() ; ++ cur)
|
||||
lpm_bytype[cur->first] += cur->second;
|
||||
|
||||
|
||||
for (map<ivl_logic_t,unsigned>::const_iterator cur = that.log_bytype.begin()
|
||||
; cur != that.log_bytype.end() ; ++ cur)
|
||||
log_bytype[cur->first] += cur->second;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
flag:DLL=sizer.tgt
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef __sizer_priv_H
|
||||
#define __sizer_priv_H
|
||||
/*
|
||||
* Copyright (c) 2014 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "ivl_target.h"
|
||||
|
||||
# include <map>
|
||||
# include <cstdio>
|
||||
|
||||
struct sizer_statistics {
|
||||
// These are the accumulated global statistics
|
||||
unsigned flop_count;
|
||||
unsigned gate_count;
|
||||
// Count adders of various dimension
|
||||
std::map<unsigned,unsigned> adder_count;
|
||||
// Different kinds of nodes that we have not accounted for
|
||||
std::map<ivl_lpm_type_t,unsigned> lpm_bytype;
|
||||
std::map<ivl_logic_t,unsigned> log_bytype;
|
||||
|
||||
inline sizer_statistics()
|
||||
{
|
||||
flop_count = 0;
|
||||
gate_count = 0;
|
||||
}
|
||||
|
||||
struct sizer_statistics& operator += (const struct sizer_statistics&that);
|
||||
};
|
||||
|
||||
extern int sizer_errors;
|
||||
extern FILE*sizer_out;
|
||||
|
||||
extern void scan_logs(ivl_scope_t scope, struct sizer_statistics&stats);
|
||||
extern void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats);
|
||||
|
||||
|
||||
extern unsigned get_nexus_width(ivl_nexus_t nex);
|
||||
|
||||
#endif
|
||||
|
|
@ -438,8 +438,16 @@ static void set_vec_to_lval_slice(ivl_lval_t lval, unsigned bit, unsigned wid)
|
|||
assert(ivl_lval_width(lval) == wid);
|
||||
|
||||
/* If the word index is a constant, then we can write
|
||||
directly to the word and save the index calculation. */
|
||||
if (word_ix == 0) {
|
||||
directly to the word and save the index
|
||||
calculation. Also, note the special case that we are
|
||||
writing to a UWIRE. In that case, use the %force/x0
|
||||
instruction to get the desired effect. */
|
||||
if (word_ix == 0 && ivl_signal_type(sig)==IVL_SIT_UWIRE) {
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu, 0;\n", part_off);
|
||||
fprintf(vvp_out, " %%force/x0 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, bit, wid);
|
||||
|
||||
} else if (word_ix == 0) {
|
||||
fprintf(vvp_out, " %%ix/load 0, %lu, 0;\n", part_off);
|
||||
fprintf(vvp_out, " %%set/x0 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, bit, wid);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,9 @@ rm -rf $RPM_BUILD_ROOT
|
|||
%attr(-,root,root) %{_libdir}/ivl%{suff}/null.tgt
|
||||
%attr(-,root,root) %{_libdir}/ivl%{suff}/null.conf
|
||||
%attr(-,root,root) %{_libdir}/ivl%{suff}/null-s.conf
|
||||
%attr(-,root,root) %{_libdir}/ivl%{suff}/sizer.tgt
|
||||
%attr(-,root,root) %{_libdir}/ivl%{suff}/sizer.conf
|
||||
%attr(-,root,root) %{_libdir}/ivl%{suff}/sizer-s.conf
|
||||
%attr(-,root,root) %{_libdir}/ivl%{suff}/stub.tgt
|
||||
%attr(-,root,root) %{_libdir}/ivl%{suff}/stub.conf
|
||||
%attr(-,root,root) %{_libdir}/ivl%{suff}/stub-s.conf
|
||||
|
|
|
|||
|
|
@ -394,6 +394,16 @@ class vvp_fun_signal_object_aa : public vvp_fun_signal_object, public automatic_
|
|||
* The vvp_wire is different from vvp_variable objects in that it
|
||||
* exists only as a filter. The vvp_wire class tree is for
|
||||
* implementing verilog wires/nets (as opposed to regs/variables).
|
||||
*
|
||||
* vvp_vpi_callback
|
||||
* |
|
||||
* |
|
||||
* vvp_net_fil_t vvp_signal_value
|
||||
* | |
|
||||
* \ /
|
||||
* \ /
|
||||
* \ /
|
||||
* vvp_wire_base
|
||||
*/
|
||||
|
||||
class vvp_wire_base : public vvp_net_fil_t, public vvp_signal_value {
|
||||
|
|
|
|||
Loading…
Reference in New Issue