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:
steve 2000-03-18 01:26:59 +00:00
parent 48de739506
commit 567de6ba39
6 changed files with 392 additions and 222 deletions

296
t-vvm.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) && !defined(macintosh) #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 #endif
# include <iostream> # include <iostream>
@ -135,7 +135,9 @@ class target_vvm : public target_t {
// of things that may be scanned multiple times. // of things that may be scanned multiple times.
map<string,bool>esignal_printed_flag; map<string,bool>esignal_printed_flag;
map<string,bool>pevent_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 // String constants that are made into vpiHandles have th
// handle name mapped by this. // handle name mapped by this.
@ -670,6 +672,7 @@ void target_vvm::start_design(ostream&os, const Design*mod)
process_counter = 0; process_counter = 0;
string_counter = 1; string_counter = 1;
number_counter = 1; number_counter = 1;
nexus_wire_counter = 1;
init_code << "static void design_init()" << endl; init_code << "static void design_init()" << endl;
init_code << "{" << endl; init_code << "{" << endl;
@ -714,8 +717,10 @@ void target_vvm::end_design(ostream&os, const Design*mod)
string_counter+1 << "];" << endl; string_counter+1 << "];" << endl;
os << "static struct __vpiNumberConst number_table[" << os << "static struct __vpiNumberConst number_table[" <<
number_counter+1 << "];" << endl; number_counter+1 << "];" << endl;
os << "static vvm_nexus_wire nexus_wire_table[" <<
nexus_wire_counter << "];" << endl;
defn.close(); defn.close();
os << "// **** Definition code" << endl; os << "// **** Definition code" << endl;
{ ifstream rdefn (defn_name); { ifstream rdefn (defn_name);
os << rdefn.rdbuf(); os << rdefn.rdbuf();
@ -803,15 +808,15 @@ void target_vvm::signal(ostream&os, const NetNet*sig)
string net_name = mangle(sig->name()); string net_name = mangle(sig->name());
for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1) { for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1) {
string nexus = mangle(nexus_from_link(&sig->pin(idx))); string nexus = nexus_from_link(&sig->pin(idx));
unsigned ncode = nexus_wire_map[nexus];
if (! nexus_printed_flag[nexus]) { if (ncode == 0) {
nexus_printed_flag[nexus] = true; nexus_wire_map[nexus] = ncode = nexus_wire_counter;
os << "vvm_nexus_wire " << nexus << "_nex;" << endl; nexus_wire_counter += 1;
} }
init_code << " " << nexus << "_nex.connect(&" << init_code << " nexus_wire_table[" << ncode <<
net_name << ", " << idx << ");" << endl; "].connect(&" << net_name << ", " << idx << ");" << endl;
} }
os << "static vvm_bitset_t<" << sig->pin_count() << "> " << 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. */ /* Connect the DataA inputs. */
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
unsigned pin = gate->pin_DataA(idx).get_pin(); string nexus = nexus_from_link(&gate->pin_DataA(idx));
string nexus = mangle(nexus_from_link(&gate->pin(pin))); unsigned ncode = nexus_wire_map[nexus];
init_code << " " << nexus << "_nex.connect(&" << init_code << " nexus_wire_table["<<ncode<<"].connect(&" <<
mangle(gate->name()) << ", " << mangle(gate->name()) << ", " <<
mangle(gate->name()) << ".key_DataA(" << idx << mangle(gate->name()) << ".key_DataA(" << idx <<
"));" << endl; "));" << endl;
@ -1031,9 +1036,10 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
/* Connect the DataB inputs. */ /* Connect the DataB inputs. */
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
unsigned pin = gate->pin_DataB(idx).get_pin(); string nexus = nexus_from_link(&gate->pin_DataB(idx));
string nexus = mangle(nexus_from_link(&gate->pin(pin))); unsigned ncode = nexus_wire_map[nexus];
init_code << " " << nexus << "_nex.connect(&" <<
init_code << " nexus_wire_table["<<ncode<<"].connect(&" <<
mangle(gate->name()) << ", " << mangle(gate->name()) << ", " <<
mangle(gate->name()) << ".key_DataB(" << idx << mangle(gate->name()) << ".key_DataB(" << idx <<
"));" << endl; "));" << endl;
@ -1042,18 +1048,20 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
/* Connect the outputs of the adder. */ /* Connect the outputs of the adder. */
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
unsigned pin = gate->pin_Result(idx).get_pin(); string nexus = nexus_from_link(&gate->pin_Result(idx));
string nexus = mangle(nexus_from_link(&gate->pin(pin))); unsigned ncode = nexus_wire_map[nexus];
init_code << " " << nexus << "_nex.connect(" <<
init_code << " nexus_wire_table["<<ncode<<"].connect(" <<
mangle(gate->name()) << ".config_rout(" << idx << mangle(gate->name()) << ".config_rout(" << idx <<
"));" << endl; "));" << endl;
} }
// Connect the carry output if necessary. // Connect the carry output if necessary.
if (gate->pin_Cout().is_linked()) { if (gate->pin_Cout().is_linked()) {
unsigned pin = gate->pin_Cout().get_pin(); string nexus = nexus_from_link(&gate->pin_Cout());
string nexus = mangle(nexus_from_link(&gate->pin(pin))); unsigned ncode = nexus_wire_map[nexus];
init_code << " " << nexus << "_nex.connect(" <<
init_code << " nexus_wire_table["<<ncode<<"].connect(" <<
mangle(gate->name()) << ".config_cout());" << endl; 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) 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() << ");" << gate->width() << "," << gate->width_dist() << ");" <<
endl; endl;
/* Connect the Data input pins... */ /* Connect the Data input pins... */
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
string nexus = mangle(nexus_from_link(&gate->pin_Data(idx))); string nexus = nexus_from_link(&gate->pin_Data(idx));
init_code << " " << nexus << "_nex.connect(&" << unsigned ncode = nexus_wire_map[nexus];
mangle(gate->name()) << ", " << mangle(gate->name())
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << ", " << mname
<< ".key_Data(" << idx << "));" << endl; << ".key_Data(" << idx << "));" << endl;
} }
/* Connect the Distance input pins... */ /* Connect the Distance input pins... */
for (unsigned idx = 0 ; idx < gate->width_dist() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->width_dist() ; idx += 1) {
string nexus = mangle(nexus_from_link(&gate->pin_Distance(idx))); string nexus = nexus_from_link(&gate->pin_Distance(idx));
init_code << " " << nexus << "_nex.connect(&" << unsigned ncode = nexus_wire_map[nexus];
mangle(gate->name()) << ", " << mangle(gate->name())
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << ", " << mname
<< ".key_Distance(" << idx << "));" << endl; << ".key_Distance(" << idx << "));" << endl;
} }
/* Connect the output drivers to the nexus nodes. */ /* Connect the output drivers to the nexus nodes. */
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
string nexus = mangle(nexus_from_link(&gate->pin_Result(idx))); string nexus = nexus_from_link(&gate->pin_Result(idx));
init_code << " " << nexus << "_nex.connect(" << unsigned ncode = nexus_wire_map[nexus];
mangle(gate->name()) << ".config_rout(" << idx <<
"));" << endl; 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... */ /* Connect DataA inputs... */
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
string nexus = mangle(nexus_from_link(&gate->pin_DataA(idx))); string nexus = nexus_from_link(&gate->pin_DataA(idx));
init_code << " " << nexus << "_nex.connect(&" << mname unsigned ncode = nexus_wire_map[nexus];
<< ", " << mname << ".key_DataA(" << idx
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << ", " << mname << ".key_DataA(" << idx
<< "));" << endl; << "));" << endl;
} }
/* Connect DataB inputs... */ /* Connect DataB inputs... */
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
string nexus = mangle(nexus_from_link(&gate->pin_DataB(idx))); string nexus = nexus_from_link(&gate->pin_DataB(idx));
init_code << " " << nexus << "_nex.connect(&" << mname unsigned ncode = nexus_wire_map[nexus];
<< ", " << mname << ".key_DataB(" << idx
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << ", " << mname << ".key_DataB(" << idx
<< "));" << endl; << "));" << endl;
} }
if (gate->pin_ALB().is_linked()) { if (gate->pin_ALB().is_linked()) {
string nexus = mangle(nexus_from_link(&gate->pin_ALB())); string nexus = nexus_from_link(&gate->pin_ALB());
init_code << " " << nexus << "_nex.connect(" << mname unsigned ncode = nexus_wire_map[nexus];
<< ".config_ALB_out());" << endl;
init_code << " nexus_wire_table["<<ncode<<"].connect("
<< mname << ".config_ALB_out());" << endl;
} }
if (gate->pin_AGB().is_linked()) { if (gate->pin_AGB().is_linked()) {
string nexus = mangle(nexus_from_link(&gate->pin_AGB())); string nexus = nexus_from_link(&gate->pin_AGB());
init_code << " " << nexus << "_nex.connect(" << mname unsigned ncode = nexus_wire_map[nexus];
<< ".config_AGB_out());" << endl;
init_code << " nexus_wire_table["<<ncode<<"].connect("
<< mname << ".config_AGB_out());" << endl;
} }
if (gate->pin_ALEB().is_linked()) { if (gate->pin_ALEB().is_linked()) {
string nexus = mangle(nexus_from_link(&gate->pin_ALEB())); string nexus = nexus_from_link(&gate->pin_ALEB());
init_code << " " << nexus << "_nex.connect(" << mname unsigned ncode = nexus_wire_map[nexus];
<< ".config_ALEB_out());" << endl;
init_code << " nexus_wire_table["<<ncode<<"].connect("
<< mname << ".config_ALEB_out());" << endl;
} }
if (gate->pin_AGEB().is_linked()) { if (gate->pin_AGEB().is_linked()) {
string nexus = mangle(nexus_from_link(&gate->pin_AGEB())); string nexus = nexus_from_link(&gate->pin_AGEB());
init_code << " " << nexus << "_nex.connect(" << mname unsigned ncode = nexus_wire_map[nexus];
<< ".config_AGEB_out());" << endl;
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) void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
{ {
string mname = mangle(mul->name()); string mname = mangle(mul->name());
os << "static vvm_mult " << mname << "(" << mul->width_r() << os << "static vvm_mult " << mname << "(" << mul->width_r() <<
"," << mul->width_a() << "," << mul->width_b() << "," << "," << mul->width_a() << "," << mul->width_b() << "," <<
mul->width_s() << ");" << endl; mul->width_s() << ");" << endl;
@ -1176,7 +1204,9 @@ void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
/* Connect the DataA inputs... */ /* Connect the DataA inputs... */
for (unsigned idx = 0 ; idx < mul->width_a() ; idx += 1) { for (unsigned idx = 0 ; idx < mul->width_a() ; idx += 1) {
string nexus = nexus_from_link(&mul->pin_DataA(idx)); 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(" << mname << ", " << mname << ".key_DataA("
<< idx << "));" << endl; << idx << "));" << endl;
} }
@ -1184,7 +1214,9 @@ void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
/* Connect the Datab inputs... */ /* Connect the Datab inputs... */
for (unsigned idx = 0 ; idx < mul->width_b() ; idx += 1) { for (unsigned idx = 0 ; idx < mul->width_b() ; idx += 1) {
string nexus = nexus_from_link(&mul->pin_DataB(idx)); 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(" << mname << ", " << mname << ".key_DataB("
<< idx << "));" << endl; << idx << "));" << endl;
} }
@ -1192,7 +1224,9 @@ void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
/* Connect the output pins... */ /* Connect the output pins... */
for (unsigned idx = 0 ; idx < mul->width_r() ; idx += 1) { for (unsigned idx = 0 ; idx < mul->width_r() ; idx += 1) {
string nexus = nexus_from_link(&mul->pin_Result(idx)); 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; << 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) void target_vvm::lpm_mux(ostream&os, const NetMux*mux)
{ {
string mname = mangle(mux->name()); 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... */ /* Connect the select inputs... */
for (unsigned idx = 0 ; idx < mux->sel_width() ; idx += 1) { for (unsigned idx = 0 ; idx < mux->sel_width() ; idx += 1) {
string nexus = mangle(nexus_from_link(&mux->pin_Sel(idx))); string nexus = nexus_from_link(&mux->pin_Sel(idx));
init_code << " " << nexus << "_nex.connect(&" unsigned ncode = nexus_wire_map[nexus];
<< mangle(mux->name()) << ", " << mangle(mux->name())
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << ", " << mname
<< ".key_Sel(" << idx << "));" << endl; << ".key_Sel(" << idx << "));" << endl;
} }
/* Connect the data inputs... */ /* Connect the data inputs... */
for (unsigned idx = 0 ; idx < mux->size() ; idx += 1) { for (unsigned idx = 0 ; idx < mux->size() ; idx += 1) {
for (unsigned wid = 0 ; wid < mux->width() ; wid += 1) { for (unsigned wid = 0 ; wid < mux->width() ; wid += 1) {
string nexus = mangle(nexus_from_link(&mux->pin_Data(wid, idx))); string nexus = nexus_from_link(&mux->pin_Data(wid, idx));
init_code << " " << nexus << "_nex.connect(&" unsigned ncode = nexus_wire_map[nexus];
<< mangle(mux->name()) << ", "
<< mangle(mux->name()) << ".key_Data(" init_code << " nexus_wire_table["<<ncode<<"]"
<< ".connect(&" << mname << ", "
<< mname << ".key_Data("
<< wid << "," << idx << "));" << endl; << wid << "," << idx << "));" << endl;
} }
} }
/* Connect the outputs... */ /* Connect the outputs... */
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1) { for (unsigned idx = 0 ; idx < mux->width() ; idx += 1) {
string nexus = mangle(nexus_from_link(&mux->pin_Result(idx))); string nexus = nexus_from_link(&mux->pin_Result(idx));
init_code << " " << nexus << "_nex.connect(" << unsigned ncode = nexus_wire_map[nexus];
mangle(mux->name()) << ".config_rout(" << idx <<
"));" << endl; 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() init_code << " // Connect inputs to gate " << gate->name()
<< "." << endl; << "." << endl;
{ string nexus = mangle(nexus_from_link(&gate->pin(0))); { string nexus = nexus_from_link(&gate->pin(0));
init_code << " " << nexus << "_nex.connect(&" << unsigned ncode = nexus_wire_map[nexus];
mangle(gate->name()) << ");" << endl; init_code << " nexus_wire_table[" << ncode <<
"].connect(&" << mangle(gate->name()) << ");" << endl;
} }
for (unsigned idx = 1 ; idx < gate->pin_count() ; idx += 1) { for (unsigned idx = 1 ; idx < gate->pin_count() ; idx += 1) {
string nexus = mangle(nexus_from_link(&gate->pin(idx))); string nexus = nexus_from_link(&gate->pin(idx));
init_code << " " << nexus << "_nex.connect(&" << unsigned ncode = nexus_wire_map[nexus];
mangle(gate->name()) << ", " << (idx-1) << ");" << endl; 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) void target_vvm::net_case_cmp(ostream&os, const NetCaseCmp*gate)
{ {
string mname = mangle(gate->name());
string nexus; string nexus;
unsigned ncode;
assert(gate->pin_count() == 3); assert(gate->pin_count() == 3);
os << "static vvm_eeq " << mangle(gate->name()) << "(" << os << "static vvm_eeq " << mname << "(" <<
gate->rise_time() << ");" << endl; gate->rise_time() << ");" << endl;
/* Connect the output pin */ /* Connect the output pin */
nexus = mangle(nexus_from_link(&gate->pin(0))); nexus = nexus_from_link(&gate->pin(0));
init_code << " " << nexus << "_nex.connect(&" << ncode = nexus_wire_map[nexus];
mangle(gate->name()) << ");" << endl; init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << ");" << endl;
/* Connect the first input */ /* Connect the first input */
nexus = mangle(nexus_from_link(&gate->pin(1))); nexus = nexus_from_link(&gate->pin(1));
init_code << " " << nexus << "_nex.connect(&" << ncode = nexus_wire_map[nexus];
mangle(gate->name()) << ", 0);" << endl; init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << ", 0);" << endl;
/* Connect the second input */ /* Connect the second input */
nexus = mangle(nexus_from_link(&gate->pin(2))); nexus = nexus_from_link(&gate->pin(2));
init_code << " " << nexus << "_nex.connect(&" << ncode = nexus_wire_map[nexus];
mangle(gate->name()) << ", 1);" << endl; 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. */ source. Write the connect calls into the init code. */
for (unsigned idx = 0 ; idx < gate->pin_count() ; idx += 1) { for (unsigned idx = 0 ; idx < gate->pin_count() ; idx += 1) {
string nexus = mangle(nexus_from_link(&gate->pin(idx))); string nexus = nexus_from_link(&gate->pin(idx));
init_code << " " << nexus << "_nex.connect(&" << unsigned ncode = nexus_wire_map[nexus];
init_code << " nexus_wire_table["<<ncode<<"].connect(&" <<
mangle(gate->name()) << ", " << idx << ");" << endl; mangle(gate->name()) << ", " << idx << ");" << endl;
} }
} }
@ -1538,8 +1588,9 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
const verinum value = rc->value(); const verinum value = rc->value();
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { 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));
defn << " " << nexus << "_nex.reg_assign("; unsigned ncode = nexus_wire_map[nexus];
defn << " nexus_wire_table[" <<ncode<< "].reg_assign(";
switch (value.get(idx)) { switch (value.get(idx)) {
case verinum::V0: case verinum::V0:
defn << "V0"; defn << "V0";
@ -1565,8 +1616,6 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
if (net->bmux()) { if (net->bmux()) {
//XXXX Not updated to nexus style??
// This is a bit select. Assign the low bit of the rval // This is a bit select. Assign the low bit of the rval
// to the selected bit of the lval. // to the selected bit of the lval.
string bval = emit_proc_rval(defn, 8, net->bmux()); 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; defn << " switch (" << bval << ".as_unsigned()) {" << endl;
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
const NetObj*cur;
unsigned pin; string nexus = nexus_from_link(&net->pin(idx));
map<string,bool> written; unsigned ncode = nexus_wire_map[nexus];
defn << " case " << idx << ":" << endl; defn << " case " << idx << ":" << endl;
for (net->pin(idx).next_link(cur, pin) defn << " nexus_wire_table["<<ncode<<"]"
; net->pin(idx) != cur->pin(pin) << ".reg_assign(" << rval << "[0]);" << endl;
; 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 << " break;" << endl; defn << " break;" << endl;
} }
defn << " }" << endl; defn << " }" << endl;
} else { } else {
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { 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));
defn << " " << nexus << "_nex.reg_assign(" << unsigned ncode = nexus_wire_map[nexus];
rval << "[" << idx << "]);" << endl; 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; defn << " switch (" << bval << ".as_unsigned()) {" << endl;
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { 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 << " case " << idx << ":" << endl;
defn << " vvm_delyed_assign(" << nexus << defn << " vvm_delayed_assign(nexus_wire_table["
"_nex, " << rval << ", " << delay << ");" << endl; << ncode << "], " << rval << ", " << delay << ");"
<< endl;
defn << " break;" << endl; defn << " break;" << endl;
} }
@ -1676,10 +1710,11 @@ void target_vvm::proc_assign_nb(ostream&os, const NetAssignNB*net)
} else { } else {
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { 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));
defn << " vvm_delayed_assign(" << nexus << unsigned ncode = nexus_wire_map[nexus];
"_nex, " << rval << "[" << idx << "], " << defn << " vvm_delayed_assign(nexus_wire_table["
delay << ");" << endl; << ncode << "], " << rval << "[" << idx << "], "
<< delay << ");" << endl;
} }
} }
} }
@ -2245,6 +2280,17 @@ extern const struct target tgt_vvm = {
}; };
/* /*
* $Log: t-vvm.cc,v $ * $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 * Revision 1.115 2000/03/17 20:21:14 steve
* Detemplatize the vvm_signal_t class. * Detemplatize the vvm_signal_t class.
* *

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # 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 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 \ O = vvm_add_sub.o vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_compare.o \
vvm_event.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 vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vpip.o
P = vpi_callback.o \ P = vpi_callback.o \

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) && !defined(macintosh) #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 #endif
# include "vvm_gates.h" # 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)); 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_and2::vvm_and2(unsigned long d)
: vvm_1bit_out(d) : vvm_1bit_out(d)
{ {
@ -298,6 +258,17 @@ void vvm_not::take_value(unsigned, vpip_bit_t val)
/* /*
* $Log: vvm_gates.cc,v $ * $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 * Revision 1.9 2000/03/17 19:24:00 steve
* nor2 and and2 optimized gates. * nor2 and and2 optimized gates.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) && !defined(macintosh) #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 #endif
# include "vvm.h" # 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 * 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 * (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 { class vvm_mux : public vvm_nexus::recvr_t {
public: public:
explicit vvm_mux() explicit vvm_mux(unsigned width, unsigned size, unsigned selwid);
{ unsigned idx; ~vvm_mux();
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;
}
void init_Sel(unsigned idx, vpip_bit_t val) void init_Sel(unsigned idx, vpip_bit_t val);
{ sel_[idx] = val; } void init_Data(unsigned idx, vpip_bit_t val);
void init_Data(unsigned idx, vpip_bit_t val) vvm_nexus::drive_t* config_rout(unsigned idx);
{ input_[idx] = val; }
vvm_nexus::drive_t* config_rout(unsigned idx) unsigned key_Sel(unsigned idx) const;
{ return out_+idx; } unsigned key_Data(unsigned wi, unsigned si) const;
unsigned key_Sel(unsigned idx) const { return idx; }
unsigned key_Data(unsigned wi, unsigned si) const
{ return 0x10000 + si*WIDTH + wi; }
private: private:
void take_value(unsigned key, vpip_bit_t val) 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 set_Sel(unsigned idx, vpip_bit_t val) unsigned width_, size_, selwid_;
{ if (sel_[idx] == val) return; vpip_bit_t*bits_;
sel_[idx] = val;
evaluate_();
}
void set_Data(unsigned idx, vpip_bit_t val) vvm_nexus::drive_t*out_;
{ if (input_[idx] == val) return;
input_[idx] = val;
evaluate_();
}
private: void evaluate_();
vpip_bit_t sel_[SELWID];
vpip_bit_t input_[WIDTH * SIZE];
vpip_bit_t output_[WIDTH];
vvm_nexus::drive_t out_[WIDTH]; private: // not implemented
vvm_mux(const vvm_mux&);
void evaluate_() vvm_mux& operator= (vvm_mux&);
{ 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]);
}
}
}; };
template <unsigned WIDTH> template <unsigned WIDTH>
@ -848,6 +814,17 @@ template <unsigned WIDTH> class vvm_pevent : public vvm_nexus::recvr_t {
/* /*
* $Log: vvm_gates.h,v $ * $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 * Revision 1.45 2000/03/17 19:24:00 steve
* nor2 and and2 optimized gates. * nor2 and and2 optimized gates.
* *

159
vvm/vvm_mux.cc Normal file
View File

@ -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.
*
*/

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) && !defined(macintosh) #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 #endif
# include "vvm_nexus.h" # include "vvm_nexus.h"
@ -34,7 +34,13 @@ vvm_nexus::vvm_nexus()
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 /* assert(recvrs_ == 0); XXXX I really should make a point to
guarantee that all the receivers that I refer to are gone, 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 $ * $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 * Revision 1.2 2000/03/16 21:45:07 steve
* Properly initialize driver and nexus values. * Properly initialize driver and nexus values.
* *