Generate references into a table of nexus objects instead of
generating lots of isolated nexus objects. Easier on linkers and compilers, Add missing nexus support for l-value bit selects, Detemplatize the vvm_mux type. Fix up the vvm_nexus destructor to disconnect from drivers.
This commit is contained in:
parent
48de739506
commit
567de6ba39
296
t-vvm.cc
296
t-vvm.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-vvm.cc,v 1.115 2000/03/17 20:21:14 steve Exp $"
|
||||
#ident "$Id: t-vvm.cc,v 1.116 2000/03/18 01:26:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
|
|
@ -135,7 +135,9 @@ class target_vvm : public target_t {
|
|||
// of things that may be scanned multiple times.
|
||||
map<string,bool>esignal_printed_flag;
|
||||
map<string,bool>pevent_printed_flag;
|
||||
map<string,bool>nexus_printed_flag;
|
||||
|
||||
map<string,unsigned>nexus_wire_map;
|
||||
unsigned nexus_wire_counter;
|
||||
|
||||
// String constants that are made into vpiHandles have th
|
||||
// handle name mapped by this.
|
||||
|
|
@ -670,6 +672,7 @@ void target_vvm::start_design(ostream&os, const Design*mod)
|
|||
process_counter = 0;
|
||||
string_counter = 1;
|
||||
number_counter = 1;
|
||||
nexus_wire_counter = 1;
|
||||
|
||||
init_code << "static void design_init()" << endl;
|
||||
init_code << "{" << endl;
|
||||
|
|
@ -714,8 +717,10 @@ void target_vvm::end_design(ostream&os, const Design*mod)
|
|||
string_counter+1 << "];" << endl;
|
||||
os << "static struct __vpiNumberConst number_table[" <<
|
||||
number_counter+1 << "];" << endl;
|
||||
|
||||
os << "static vvm_nexus_wire nexus_wire_table[" <<
|
||||
nexus_wire_counter << "];" << endl;
|
||||
defn.close();
|
||||
|
||||
os << "// **** Definition code" << endl;
|
||||
{ ifstream rdefn (defn_name);
|
||||
os << rdefn.rdbuf();
|
||||
|
|
@ -803,15 +808,15 @@ void target_vvm::signal(ostream&os, const NetNet*sig)
|
|||
string net_name = mangle(sig->name());
|
||||
|
||||
for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&sig->pin(idx)));
|
||||
|
||||
if (! nexus_printed_flag[nexus]) {
|
||||
nexus_printed_flag[nexus] = true;
|
||||
os << "vvm_nexus_wire " << nexus << "_nex;" << endl;
|
||||
string nexus = nexus_from_link(&sig->pin(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
if (ncode == 0) {
|
||||
nexus_wire_map[nexus] = ncode = nexus_wire_counter;
|
||||
nexus_wire_counter += 1;
|
||||
}
|
||||
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
net_name << ", " << idx << ");" << endl;
|
||||
init_code << " nexus_wire_table[" << ncode <<
|
||||
"].connect(&" << net_name << ", " << idx << ");" << endl;
|
||||
}
|
||||
|
||||
os << "static vvm_bitset_t<" << sig->pin_count() << "> " <<
|
||||
|
|
@ -1020,9 +1025,9 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
|||
/* Connect the DataA inputs. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
|
||||
unsigned pin = gate->pin_DataA(idx).get_pin();
|
||||
string nexus = mangle(nexus_from_link(&gate->pin(pin)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
string nexus = nexus_from_link(&gate->pin_DataA(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&" <<
|
||||
mangle(gate->name()) << ", " <<
|
||||
mangle(gate->name()) << ".key_DataA(" << idx <<
|
||||
"));" << endl;
|
||||
|
|
@ -1031,9 +1036,10 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
|||
/* Connect the DataB inputs. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
|
||||
unsigned pin = gate->pin_DataB(idx).get_pin();
|
||||
string nexus = mangle(nexus_from_link(&gate->pin(pin)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
string nexus = nexus_from_link(&gate->pin_DataB(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&" <<
|
||||
mangle(gate->name()) << ", " <<
|
||||
mangle(gate->name()) << ".key_DataB(" << idx <<
|
||||
"));" << endl;
|
||||
|
|
@ -1042,18 +1048,20 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
|||
/* Connect the outputs of the adder. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
|
||||
unsigned pin = gate->pin_Result(idx).get_pin();
|
||||
string nexus = mangle(nexus_from_link(&gate->pin(pin)));
|
||||
init_code << " " << nexus << "_nex.connect(" <<
|
||||
string nexus = nexus_from_link(&gate->pin_Result(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(" <<
|
||||
mangle(gate->name()) << ".config_rout(" << idx <<
|
||||
"));" << endl;
|
||||
}
|
||||
|
||||
// Connect the carry output if necessary.
|
||||
if (gate->pin_Cout().is_linked()) {
|
||||
unsigned pin = gate->pin_Cout().get_pin();
|
||||
string nexus = mangle(nexus_from_link(&gate->pin(pin)));
|
||||
init_code << " " << nexus << "_nex.connect(" <<
|
||||
string nexus = nexus_from_link(&gate->pin_Cout());
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(" <<
|
||||
mangle(gate->name()) << ".config_cout());" << endl;
|
||||
}
|
||||
|
||||
|
|
@ -1072,32 +1080,39 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
|||
|
||||
void target_vvm::lpm_clshift(ostream&os, const NetCLShift*gate)
|
||||
{
|
||||
os << "static vvm_clshift " << mangle(gate->name()) << "(" <<
|
||||
string mname = mangle(gate->name());
|
||||
|
||||
os << "static vvm_clshift " << mname << "(" <<
|
||||
gate->width() << "," << gate->width_dist() << ");" <<
|
||||
endl;
|
||||
|
||||
/* Connect the Data input pins... */
|
||||
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_Data(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
mangle(gate->name()) << ", " << mangle(gate->name())
|
||||
string nexus = nexus_from_link(&gate->pin_Data(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", " << mname
|
||||
<< ".key_Data(" << idx << "));" << endl;
|
||||
}
|
||||
|
||||
/* Connect the Distance input pins... */
|
||||
for (unsigned idx = 0 ; idx < gate->width_dist() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_Distance(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
mangle(gate->name()) << ", " << mangle(gate->name())
|
||||
string nexus = nexus_from_link(&gate->pin_Distance(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", " << mname
|
||||
<< ".key_Distance(" << idx << "));" << endl;
|
||||
}
|
||||
|
||||
/* Connect the output drivers to the nexus nodes. */
|
||||
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_Result(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(" <<
|
||||
mangle(gate->name()) << ".config_rout(" << idx <<
|
||||
"));" << endl;
|
||||
string nexus = nexus_from_link(&gate->pin_Result(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect("
|
||||
<< mname << ".config_rout(" << idx << "));" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1110,43 +1125,55 @@ void target_vvm::lpm_compare(ostream&os, const NetCompare*gate)
|
|||
|
||||
/* Connect DataA inputs... */
|
||||
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_DataA(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(&" << mname
|
||||
<< ", " << mname << ".key_DataA(" << idx
|
||||
string nexus = nexus_from_link(&gate->pin_DataA(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", " << mname << ".key_DataA(" << idx
|
||||
<< "));" << endl;
|
||||
}
|
||||
|
||||
/* Connect DataB inputs... */
|
||||
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_DataB(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(&" << mname
|
||||
<< ", " << mname << ".key_DataB(" << idx
|
||||
string nexus = nexus_from_link(&gate->pin_DataB(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", " << mname << ".key_DataB(" << idx
|
||||
<< "));" << endl;
|
||||
}
|
||||
|
||||
if (gate->pin_ALB().is_linked()) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_ALB()));
|
||||
init_code << " " << nexus << "_nex.connect(" << mname
|
||||
<< ".config_ALB_out());" << endl;
|
||||
string nexus = nexus_from_link(&gate->pin_ALB());
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect("
|
||||
<< mname << ".config_ALB_out());" << endl;
|
||||
}
|
||||
|
||||
if (gate->pin_AGB().is_linked()) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_AGB()));
|
||||
init_code << " " << nexus << "_nex.connect(" << mname
|
||||
<< ".config_AGB_out());" << endl;
|
||||
string nexus = nexus_from_link(&gate->pin_AGB());
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect("
|
||||
<< mname << ".config_AGB_out());" << endl;
|
||||
}
|
||||
|
||||
|
||||
if (gate->pin_ALEB().is_linked()) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_ALEB()));
|
||||
init_code << " " << nexus << "_nex.connect(" << mname
|
||||
<< ".config_ALEB_out());" << endl;
|
||||
string nexus = nexus_from_link(&gate->pin_ALEB());
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect("
|
||||
<< mname << ".config_ALEB_out());" << endl;
|
||||
}
|
||||
|
||||
if (gate->pin_AGEB().is_linked()) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin_AGEB()));
|
||||
init_code << " " << nexus << "_nex.connect(" << mname
|
||||
<< ".config_AGEB_out());" << endl;
|
||||
string nexus = nexus_from_link(&gate->pin_AGEB());
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect("
|
||||
<< mname << ".config_AGEB_out());" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1168,6 +1195,7 @@ void target_vvm::lpm_ff(ostream&os, const NetFF*gate)
|
|||
void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
|
||||
{
|
||||
string mname = mangle(mul->name());
|
||||
|
||||
os << "static vvm_mult " << mname << "(" << mul->width_r() <<
|
||||
"," << mul->width_a() << "," << mul->width_b() << "," <<
|
||||
mul->width_s() << ");" << endl;
|
||||
|
|
@ -1176,7 +1204,9 @@ void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
|
|||
/* Connect the DataA inputs... */
|
||||
for (unsigned idx = 0 ; idx < mul->width_a() ; idx += 1) {
|
||||
string nexus = nexus_from_link(&mul->pin_DataA(idx));
|
||||
init_code << " " << mangle(nexus) << "_nex.connect(&"
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", " << mname << ".key_DataA("
|
||||
<< idx << "));" << endl;
|
||||
}
|
||||
|
|
@ -1184,7 +1214,9 @@ void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
|
|||
/* Connect the Datab inputs... */
|
||||
for (unsigned idx = 0 ; idx < mul->width_b() ; idx += 1) {
|
||||
string nexus = nexus_from_link(&mul->pin_DataB(idx));
|
||||
init_code << " " << mangle(nexus) << "_nex.connect(&"
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", " << mname << ".key_DataB("
|
||||
<< idx << "));" << endl;
|
||||
}
|
||||
|
|
@ -1192,7 +1224,9 @@ void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
|
|||
/* Connect the output pins... */
|
||||
for (unsigned idx = 0 ; idx < mul->width_r() ; idx += 1) {
|
||||
string nexus = nexus_from_link(&mul->pin_Result(idx));
|
||||
init_code << " " << mangle(nexus) << "_nex.connect("
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect("
|
||||
<< mname << ".config_rout(" << idx << "));" << endl;
|
||||
}
|
||||
}
|
||||
|
|
@ -1200,34 +1234,40 @@ void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
|
|||
void target_vvm::lpm_mux(ostream&os, const NetMux*mux)
|
||||
{
|
||||
string mname = mangle(mux->name());
|
||||
os << "static vvm_mux<" << mux->width() << "," << mux->size() <<
|
||||
"," << mux->sel_width() << "> " << mname << ";" << endl;
|
||||
|
||||
os << "static vvm_mux " << mname << "(" << mux->width() << ","
|
||||
<< mux->size() << "," << mux->sel_width() << ");" << endl;
|
||||
|
||||
/* Connect the select inputs... */
|
||||
for (unsigned idx = 0 ; idx < mux->sel_width() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&mux->pin_Sel(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(&"
|
||||
<< mangle(mux->name()) << ", " << mangle(mux->name())
|
||||
string nexus = nexus_from_link(&mux->pin_Sel(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", " << mname
|
||||
<< ".key_Sel(" << idx << "));" << endl;
|
||||
}
|
||||
|
||||
/* Connect the data inputs... */
|
||||
for (unsigned idx = 0 ; idx < mux->size() ; idx += 1) {
|
||||
for (unsigned wid = 0 ; wid < mux->width() ; wid += 1) {
|
||||
string nexus = mangle(nexus_from_link(&mux->pin_Data(wid, idx)));
|
||||
init_code << " " << nexus << "_nex.connect(&"
|
||||
<< mangle(mux->name()) << ", "
|
||||
<< mangle(mux->name()) << ".key_Data("
|
||||
string nexus = nexus_from_link(&mux->pin_Data(wid, idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"]"
|
||||
<< ".connect(&" << mname << ", "
|
||||
<< mname << ".key_Data("
|
||||
<< wid << "," << idx << "));" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect the outputs... */
|
||||
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&mux->pin_Result(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(" <<
|
||||
mangle(mux->name()) << ".config_rout(" << idx <<
|
||||
"));" << endl;
|
||||
string nexus = nexus_from_link(&mux->pin_Result(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect("
|
||||
<< mname << ".config_rout(" << idx << "));" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1309,15 +1349,18 @@ void target_vvm::logic(ostream&os, const NetLogic*gate)
|
|||
init_code << " // Connect inputs to gate " << gate->name()
|
||||
<< "." << endl;
|
||||
|
||||
{ string nexus = mangle(nexus_from_link(&gate->pin(0)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
mangle(gate->name()) << ");" << endl;
|
||||
{ string nexus = nexus_from_link(&gate->pin(0));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
init_code << " nexus_wire_table[" << ncode <<
|
||||
"].connect(&" << mangle(gate->name()) << ");" << endl;
|
||||
}
|
||||
|
||||
for (unsigned idx = 1 ; idx < gate->pin_count() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
mangle(gate->name()) << ", " << (idx-1) << ");" << endl;
|
||||
string nexus = nexus_from_link(&gate->pin(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
init_code << " nexus_wire_table[" << ncode
|
||||
<< "].connect(&" << mangle(gate->name()) << ", "
|
||||
<< (idx-1) << ");" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1408,29 +1451,34 @@ void target_vvm::net_assign_nb(ostream&os, const NetAssignNB*net)
|
|||
|
||||
void target_vvm::net_case_cmp(ostream&os, const NetCaseCmp*gate)
|
||||
{
|
||||
string mname = mangle(gate->name());
|
||||
string nexus;
|
||||
unsigned ncode;
|
||||
|
||||
assert(gate->pin_count() == 3);
|
||||
os << "static vvm_eeq " << mangle(gate->name()) << "(" <<
|
||||
os << "static vvm_eeq " << mname << "(" <<
|
||||
gate->rise_time() << ");" << endl;
|
||||
|
||||
/* Connect the output pin */
|
||||
nexus = mangle(nexus_from_link(&gate->pin(0)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
mangle(gate->name()) << ");" << endl;
|
||||
nexus = nexus_from_link(&gate->pin(0));
|
||||
ncode = nexus_wire_map[nexus];
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ");" << endl;
|
||||
|
||||
/* Connect the first input */
|
||||
nexus = mangle(nexus_from_link(&gate->pin(1)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
mangle(gate->name()) << ", 0);" << endl;
|
||||
nexus = nexus_from_link(&gate->pin(1));
|
||||
ncode = nexus_wire_map[nexus];
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", 0);" << endl;
|
||||
|
||||
/* Connect the second input */
|
||||
nexus = mangle(nexus_from_link(&gate->pin(2)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
mangle(gate->name()) << ", 1);" << endl;
|
||||
nexus = nexus_from_link(&gate->pin(2));
|
||||
ncode = nexus_wire_map[nexus];
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
|
||||
<< mname << ", 1);" << endl;
|
||||
|
||||
|
||||
start_code << " " << mangle(gate->name()) << ".start();" << endl;
|
||||
start_code << " " << mname << ".start();" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1487,8 +1535,10 @@ void target_vvm::net_event(ostream&os, const NetNEvent*gate)
|
|||
source. Write the connect calls into the init code. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < gate->pin_count() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&gate->pin(idx)));
|
||||
init_code << " " << nexus << "_nex.connect(&" <<
|
||||
string nexus = nexus_from_link(&gate->pin(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
init_code << " nexus_wire_table["<<ncode<<"].connect(&" <<
|
||||
mangle(gate->name()) << ", " << idx << ");" << endl;
|
||||
}
|
||||
}
|
||||
|
|
@ -1538,8 +1588,9 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
|
|||
const verinum value = rc->value();
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&net->pin(idx)));
|
||||
defn << " " << nexus << "_nex.reg_assign(";
|
||||
string nexus = nexus_from_link(&net->pin(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
defn << " nexus_wire_table[" <<ncode<< "].reg_assign(";
|
||||
switch (value.get(idx)) {
|
||||
case verinum::V0:
|
||||
defn << "V0";
|
||||
|
|
@ -1565,8 +1616,6 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
|
|||
|
||||
if (net->bmux()) {
|
||||
|
||||
//XXXX Not updated to nexus style??
|
||||
|
||||
// This is a bit select. Assign the low bit of the rval
|
||||
// to the selected bit of the lval.
|
||||
string bval = emit_proc_rval(defn, 8, net->bmux());
|
||||
|
|
@ -1574,43 +1623,26 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
|
|||
defn << " switch (" << bval << ".as_unsigned()) {" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
const NetObj*cur;
|
||||
unsigned pin;
|
||||
map<string,bool> written;
|
||||
|
||||
string nexus = nexus_from_link(&net->pin(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
defn << " case " << idx << ":" << endl;
|
||||
|
||||
for (net->pin(idx).next_link(cur, pin)
|
||||
; net->pin(idx) != cur->pin(pin)
|
||||
; cur->pin(pin).next_link(cur, pin)) {
|
||||
|
||||
// Skip output only pins.
|
||||
if (cur->pin(pin).get_dir() == NetObj::Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
// It is possible for a named device to show up
|
||||
// several times in a link. This is the classic
|
||||
// case with NetESignal objects, which are
|
||||
// repeated for each expression that uses it.
|
||||
if (written[cur->name()])
|
||||
continue;
|
||||
|
||||
written[cur->name()] = true;
|
||||
defn << " " << mangle(cur->name()) <<
|
||||
".set_" << cur->pin(pin).get_name() <<
|
||||
"(" << cur->pin(pin).get_inst() <<
|
||||
", " << rval << "[0]);" << endl;
|
||||
}
|
||||
|
||||
defn << " nexus_wire_table["<<ncode<<"]"
|
||||
<< ".reg_assign(" << rval << "[0]);" << endl;
|
||||
defn << " break;" << endl;
|
||||
|
||||
}
|
||||
|
||||
defn << " }" << endl;
|
||||
|
||||
} else {
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&net->pin(idx)));
|
||||
defn << " " << nexus << "_nex.reg_assign(" <<
|
||||
rval << "[" << idx << "]);" << endl;
|
||||
string nexus = nexus_from_link(&net->pin(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
defn << " nexus_wire_table["<<ncode<<"].reg_assign("
|
||||
<< rval << "[" << idx << "]);" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1664,11 +1696,13 @@ void target_vvm::proc_assign_nb(ostream&os, const NetAssignNB*net)
|
|||
defn << " switch (" << bval << ".as_unsigned()) {" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&net->pin(idx)));
|
||||
string nexus = nexus_from_link(&net->pin(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
|
||||
defn << " case " << idx << ":" << endl;
|
||||
defn << " vvm_delyed_assign(" << nexus <<
|
||||
"_nex, " << rval << ", " << delay << ");" << endl;
|
||||
defn << " vvm_delayed_assign(nexus_wire_table["
|
||||
<< ncode << "], " << rval << ", " << delay << ");"
|
||||
<< endl;
|
||||
defn << " break;" << endl;
|
||||
}
|
||||
|
||||
|
|
@ -1676,10 +1710,11 @@ void target_vvm::proc_assign_nb(ostream&os, const NetAssignNB*net)
|
|||
|
||||
} else {
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
string nexus = mangle(nexus_from_link(&net->pin(idx)));
|
||||
defn << " vvm_delayed_assign(" << nexus <<
|
||||
"_nex, " << rval << "[" << idx << "], " <<
|
||||
delay << ");" << endl;
|
||||
string nexus = nexus_from_link(&net->pin(idx));
|
||||
unsigned ncode = nexus_wire_map[nexus];
|
||||
defn << " vvm_delayed_assign(nexus_wire_table["
|
||||
<< ncode << "], " << rval << "[" << idx << "], "
|
||||
<< delay << ");" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2245,6 +2280,17 @@ extern const struct target tgt_vvm = {
|
|||
};
|
||||
/*
|
||||
* $Log: t-vvm.cc,v $
|
||||
* Revision 1.116 2000/03/18 01:26:59 steve
|
||||
* Generate references into a table of nexus objects instead of
|
||||
* generating lots of isolated nexus objects. Easier on linkers
|
||||
* and compilers,
|
||||
*
|
||||
* Add missing nexus support for l-value bit selects,
|
||||
*
|
||||
* Detemplatize the vvm_mux type.
|
||||
*
|
||||
* Fix up the vvm_nexus destructor to disconnect from drivers.
|
||||
*
|
||||
* Revision 1.115 2000/03/17 20:21:14 steve
|
||||
* Detemplatize the vvm_signal_t class.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.23 2000/03/17 17:25:53 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.24 2000/03/18 01:26:59 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -60,7 +60,7 @@ all: libvvm.a
|
|||
|
||||
O = vvm_add_sub.o vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_compare.o \
|
||||
vvm_event.o \
|
||||
vvm_func.o vvm_gates.o vvm_mult.o \
|
||||
vvm_func.o vvm_gates.o vvm_mult.o vvm_mux.o \
|
||||
vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vpip.o
|
||||
|
||||
P = vpi_callback.o \
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vvm_gates.cc,v 1.9 2000/03/17 19:24:00 steve Exp $"
|
||||
#ident "$Id: vvm_gates.cc,v 1.10 2000/03/18 01:27:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm_gates.h"
|
||||
|
|
@ -94,46 +94,6 @@ vpip_bit_t compute_xnor(const vpip_bit_t*inp, unsigned count)
|
|||
return v_not(compute_xor(inp,count));
|
||||
}
|
||||
|
||||
void compute_mux(vpip_bit_t*out, unsigned wid,
|
||||
const vpip_bit_t*sel, unsigned swid,
|
||||
const vpip_bit_t*dat, unsigned size)
|
||||
{
|
||||
unsigned tmp = 0;
|
||||
for (unsigned idx = 0 ; idx < swid ; idx += 1)
|
||||
switch (sel[idx]) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
tmp |= (1<<idx);
|
||||
break;
|
||||
default:
|
||||
tmp = size;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp >= size) {
|
||||
|
||||
if (swid > 1) {
|
||||
for (unsigned idx = 0; idx < wid ; idx += 1)
|
||||
out[idx] = Vx;
|
||||
} else {
|
||||
const unsigned b0 = 0;
|
||||
const unsigned b1 = wid;
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (dat[idx+b0] == dat[idx+b1])
|
||||
out[idx] = dat[idx+b0];
|
||||
else
|
||||
out[idx] = Vx;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
unsigned b = tmp * wid;
|
||||
for (unsigned idx = 0; idx < wid ; idx += 1)
|
||||
out[idx] = dat[idx+b];
|
||||
}
|
||||
}
|
||||
|
||||
vvm_and2::vvm_and2(unsigned long d)
|
||||
: vvm_1bit_out(d)
|
||||
{
|
||||
|
|
@ -298,6 +258,17 @@ void vvm_not::take_value(unsigned, vpip_bit_t val)
|
|||
|
||||
/*
|
||||
* $Log: vvm_gates.cc,v $
|
||||
* Revision 1.10 2000/03/18 01:27:00 steve
|
||||
* Generate references into a table of nexus objects instead of
|
||||
* generating lots of isolated nexus objects. Easier on linkers
|
||||
* and compilers,
|
||||
*
|
||||
* Add missing nexus support for l-value bit selects,
|
||||
*
|
||||
* Detemplatize the vvm_mux type.
|
||||
*
|
||||
* Fix up the vvm_nexus destructor to disconnect from drivers.
|
||||
*
|
||||
* Revision 1.9 2000/03/17 19:24:00 steve
|
||||
* nor2 and and2 optimized gates.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vvm_gates.h,v 1.45 2000/03/17 19:24:00 steve Exp $"
|
||||
#ident "$Id: vvm_gates.h,v 1.46 2000/03/18 01:27:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
|
|
@ -328,70 +328,36 @@ class vvm_mult : public vvm_nexus::recvr_t {
|
|||
/*
|
||||
* This class supports mux devices. The width is the width of the data
|
||||
* (or bus) path, SIZE is the number of alternative inputs and SELWID
|
||||
* is the size (in bits) of the selector input.
|
||||
* is the size (in bits) of the selector input. The device passes to
|
||||
* the output the bits of the input selected by the selector.
|
||||
*/
|
||||
template <unsigned WIDTH, unsigned SIZE, unsigned SELWID>
|
||||
class vvm_mux : public vvm_nexus::recvr_t {
|
||||
|
||||
public:
|
||||
explicit vvm_mux()
|
||||
{ unsigned idx;
|
||||
for (idx = 0 ; idx < WIDTH ; idx += 1) output_[idx] = Vx;
|
||||
for (idx = 0 ; idx < SELWID; idx += 1) sel_[idx] = Vx;
|
||||
for (idx = 0 ; idx < WIDTH*SIZE; idx += 1) input_[idx] = Vx;
|
||||
}
|
||||
explicit vvm_mux(unsigned width, unsigned size, unsigned selwid);
|
||||
~vvm_mux();
|
||||
|
||||
void init_Sel(unsigned idx, vpip_bit_t val)
|
||||
{ sel_[idx] = val; }
|
||||
void init_Sel(unsigned idx, vpip_bit_t val);
|
||||
void init_Data(unsigned idx, vpip_bit_t val);
|
||||
|
||||
void init_Data(unsigned idx, vpip_bit_t val)
|
||||
{ input_[idx] = val; }
|
||||
vvm_nexus::drive_t* config_rout(unsigned idx);
|
||||
|
||||
vvm_nexus::drive_t* config_rout(unsigned idx)
|
||||
{ return out_+idx; }
|
||||
|
||||
unsigned key_Sel(unsigned idx) const { return idx; }
|
||||
unsigned key_Data(unsigned wi, unsigned si) const
|
||||
{ return 0x10000 + si*WIDTH + wi; }
|
||||
unsigned key_Sel(unsigned idx) const;
|
||||
unsigned key_Data(unsigned wi, unsigned si) const;
|
||||
|
||||
private:
|
||||
void take_value(unsigned key, vpip_bit_t val)
|
||||
{ unsigned code = key >> 16;
|
||||
unsigned idx = key & 0xffff;
|
||||
if (code == 1)
|
||||
set_Data(idx, val);
|
||||
else
|
||||
set_Sel(idx, val);
|
||||
}
|
||||
void take_value(unsigned key, vpip_bit_t val);
|
||||
|
||||
void set_Sel(unsigned idx, vpip_bit_t val)
|
||||
{ if (sel_[idx] == val) return;
|
||||
sel_[idx] = val;
|
||||
evaluate_();
|
||||
}
|
||||
unsigned width_, size_, selwid_;
|
||||
vpip_bit_t*bits_;
|
||||
|
||||
void set_Data(unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx] == val) return;
|
||||
input_[idx] = val;
|
||||
evaluate_();
|
||||
}
|
||||
vvm_nexus::drive_t*out_;
|
||||
|
||||
private:
|
||||
vpip_bit_t sel_[SELWID];
|
||||
vpip_bit_t input_[WIDTH * SIZE];
|
||||
vpip_bit_t output_[WIDTH];
|
||||
void evaluate_();
|
||||
|
||||
vvm_nexus::drive_t out_[WIDTH];
|
||||
|
||||
void evaluate_()
|
||||
{ vpip_bit_t tmp[WIDTH];
|
||||
compute_mux(tmp, WIDTH, sel_, SELWID, input_, SIZE);
|
||||
for (unsigned idx = 0 ; idx < WIDTH ; idx += 1)
|
||||
if (tmp[idx] != output_[idx]) {
|
||||
output_[idx] = tmp[idx];
|
||||
out_[idx].set_value(output_[idx]);
|
||||
}
|
||||
}
|
||||
private: // not implemented
|
||||
vvm_mux(const vvm_mux&);
|
||||
vvm_mux& operator= (vvm_mux&);
|
||||
};
|
||||
|
||||
template <unsigned WIDTH>
|
||||
|
|
@ -848,6 +814,17 @@ template <unsigned WIDTH> class vvm_pevent : public vvm_nexus::recvr_t {
|
|||
|
||||
/*
|
||||
* $Log: vvm_gates.h,v $
|
||||
* Revision 1.46 2000/03/18 01:27:00 steve
|
||||
* Generate references into a table of nexus objects instead of
|
||||
* generating lots of isolated nexus objects. Easier on linkers
|
||||
* and compilers,
|
||||
*
|
||||
* Add missing nexus support for l-value bit selects,
|
||||
*
|
||||
* Detemplatize the vvm_mux type.
|
||||
*
|
||||
* Fix up the vvm_nexus destructor to disconnect from drivers.
|
||||
*
|
||||
* Revision 1.45 2000/03/17 19:24:00 steve
|
||||
* nor2 and and2 optimized gates.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2000 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vvm_mux.cc,v 1.1 2000/03/18 01:27:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm_gates.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* The array of bits is arranged as:
|
||||
*
|
||||
* oooo ss 0000 1111 2222 3333 ...
|
||||
*
|
||||
*/
|
||||
vvm_mux::vvm_mux(unsigned w, unsigned s, unsigned sw)
|
||||
: width_(w), size_(s), selwid_(sw)
|
||||
{
|
||||
bits_ = new vpip_bit_t[width_*size_+selwid_+width_];
|
||||
out_ = new vvm_nexus::drive_t[width_];
|
||||
|
||||
for (unsigned idx = 0 ; idx < width_*size_+selwid_+width_ ; idx += 1)
|
||||
bits_[idx] = Vx;
|
||||
}
|
||||
|
||||
vvm_mux::~vvm_mux()
|
||||
{
|
||||
delete[]out_;
|
||||
delete[]bits_;
|
||||
}
|
||||
|
||||
vvm_nexus::drive_t* vvm_mux::config_rout(unsigned idx)
|
||||
{
|
||||
assert(idx < width_);
|
||||
return out_+idx;
|
||||
}
|
||||
|
||||
unsigned vvm_mux::key_Sel(unsigned idx) const
|
||||
{
|
||||
assert(idx < selwid_);
|
||||
return idx + width_;
|
||||
}
|
||||
|
||||
unsigned vvm_mux::key_Data(unsigned wi, unsigned si) const
|
||||
{
|
||||
assert(si < size_);
|
||||
assert(wi < width_);
|
||||
return width_ + selwid_ + si*width_ + wi;
|
||||
}
|
||||
|
||||
void vvm_mux::init_Sel(unsigned idx, vpip_bit_t val)
|
||||
{
|
||||
assert(idx < selwid_);
|
||||
bits_[width_+idx] = val;
|
||||
}
|
||||
|
||||
void vvm_mux::init_Data(unsigned idx, vpip_bit_t val)
|
||||
{
|
||||
assert(idx < width_*size_);
|
||||
bits_[width_+selwid_+idx] = val;
|
||||
}
|
||||
|
||||
void vvm_mux::take_value(unsigned key, vpip_bit_t val)
|
||||
{
|
||||
if (bits_[key] == val)
|
||||
return;
|
||||
|
||||
bits_[key] = val;
|
||||
evaluate_();
|
||||
}
|
||||
|
||||
void vvm_mux::evaluate_()
|
||||
{
|
||||
vpip_bit_t*tmp = new vpip_bit_t[width_];
|
||||
|
||||
vpip_bit_t*sel = bits_+width_;
|
||||
vpip_bit_t*inp = bits_+width_+selwid_;
|
||||
|
||||
compute_mux(tmp, width_, sel, selwid_, inp, size_);
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1)
|
||||
if (tmp[idx] != bits_[idx]) {
|
||||
bits_[idx] = tmp[idx];
|
||||
out_[idx].set_value(bits_[idx]);
|
||||
}
|
||||
|
||||
delete[]tmp;
|
||||
}
|
||||
|
||||
void compute_mux(vpip_bit_t*out, unsigned wid,
|
||||
const vpip_bit_t*sel, unsigned swid,
|
||||
const vpip_bit_t*dat, unsigned size)
|
||||
{
|
||||
unsigned tmp = 0;
|
||||
for (unsigned idx = 0 ; idx < swid ; idx += 1)
|
||||
switch (sel[idx]) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
tmp |= (1<<idx);
|
||||
break;
|
||||
default:
|
||||
tmp = size;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp >= size) {
|
||||
|
||||
if (swid > 1) {
|
||||
for (unsigned idx = 0; idx < wid ; idx += 1)
|
||||
out[idx] = Vx;
|
||||
} else {
|
||||
const unsigned b0 = 0;
|
||||
const unsigned b1 = wid;
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (dat[idx+b0] == dat[idx+b1])
|
||||
out[idx] = dat[idx+b0];
|
||||
else
|
||||
out[idx] = Vx;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
unsigned b = tmp * wid;
|
||||
for (unsigned idx = 0; idx < wid ; idx += 1)
|
||||
out[idx] = dat[idx+b];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vvm_mux.cc,v $
|
||||
* Revision 1.1 2000/03/18 01:27:00 steve
|
||||
* Generate references into a table of nexus objects instead of
|
||||
* generating lots of isolated nexus objects. Easier on linkers
|
||||
* and compilers,
|
||||
*
|
||||
* Add missing nexus support for l-value bit selects,
|
||||
*
|
||||
* Detemplatize the vvm_mux type.
|
||||
*
|
||||
* Fix up the vvm_nexus destructor to disconnect from drivers.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vvm_nexus.cc,v 1.2 2000/03/16 21:45:07 steve Exp $"
|
||||
#ident "$Id: vvm_nexus.cc,v 1.3 2000/03/18 01:27:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm_nexus.h"
|
||||
|
|
@ -34,7 +34,13 @@ vvm_nexus::vvm_nexus()
|
|||
|
||||
vvm_nexus::~vvm_nexus()
|
||||
{
|
||||
assert(drivers_ == 0);
|
||||
while (drivers_) {
|
||||
drive_t*cur = drivers_;
|
||||
drivers_ = cur->next_;
|
||||
assert(cur->nexus_ == this);
|
||||
cur->nexus_ = 0;
|
||||
cur->next_ = 0;
|
||||
}
|
||||
|
||||
/* assert(recvrs_ == 0); XXXX I really should make a point to
|
||||
guarantee that all the receivers that I refer to are gone,
|
||||
|
|
@ -227,6 +233,17 @@ void vvm_delayed_assign(vvm_nexus&l_val, vpip_bit_t r_val,
|
|||
|
||||
/*
|
||||
* $Log: vvm_nexus.cc,v $
|
||||
* Revision 1.3 2000/03/18 01:27:00 steve
|
||||
* Generate references into a table of nexus objects instead of
|
||||
* generating lots of isolated nexus objects. Easier on linkers
|
||||
* and compilers,
|
||||
*
|
||||
* Add missing nexus support for l-value bit selects,
|
||||
*
|
||||
* Detemplatize the vvm_mux type.
|
||||
*
|
||||
* Fix up the vvm_nexus destructor to disconnect from drivers.
|
||||
*
|
||||
* Revision 1.2 2000/03/16 21:45:07 steve
|
||||
* Properly initialize driver and nexus values.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue