Apply sequential UDP rework from Stephan Boettcher (PR#39)

This commit is contained in:
steve 2000-11-04 06:36:24 +00:00
parent 5415dd70c5
commit 61ad0b23c8
6 changed files with 190 additions and 233 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: design_dump.cc,v 1.101 2000/10/28 00:51:41 steve Exp $"
#ident "$Id: design_dump.cc,v 1.102 2000/11/04 06:36:24 steve Exp $"
#endif
/*
@ -395,7 +395,7 @@ void NetUDP::dump_comb_(ostream&o, unsigned ind) const
void NetUDP::dump_node(ostream&o, unsigned ind) const
{
if (sequential_)
if (is_sequential())
dump_sequ_(o, ind);
else
dump_comb_(o, ind);
@ -975,6 +975,9 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.102 2000/11/04 06:36:24 steve
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
*
* Revision 1.101 2000/10/28 00:51:41 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls

View File

@ -17,26 +17,19 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: net_udp.cc,v 1.1 2000/03/29 04:37:11 steve Exp $"
#ident "$Id: net_udp.cc,v 1.2 2000/11/04 06:36:24 steve Exp $"
#endif
# include "netlist.h"
NetUDP::NetUDP(const string&n, unsigned pins, bool sequ)
: NetNode(n, pins), sequential_(sequ), init_('x')
{
pin(0).set_dir(Link::OUTPUT);
for (unsigned idx = 1 ; idx < pins ; idx += 1)
pin(idx).set_dir(Link::INPUT);
}
bool NetUDP::set_table(const string&input, char output)
{
assert((output == '0') || (output == '1') || (sequential_ &&
(output == '-')));
assert((output == '0') || (output == '1')
|| (is_sequential() && (output == '-')));
if (sequential_) {
cm_[input] = output;
if (is_sequential()) {
assert(input.length() == pin_count());
/* XXXX Need to check to make sure that the input vector
contains a legal combination of characters. */
@ -46,8 +39,7 @@ bool NetUDP::set_table(const string&input, char output)
assert(input.length() == (pin_count()-1));
/* XXXX Need to check to make sure that the input vector
contains a legal combination of characters. In
combinational UDPs, only 0, 1 and x are allowed. */
cm_[input] = output;
combinational UDPs, only 0, 1, x, and ? are allowed. */
return true;
}
@ -124,7 +116,7 @@ char NetUDP::table_lookup(const string&from, char to, unsigned pin) const
void NetUDP::set_initial(char val)
{
assert(sequential_);
assert(is_sequential());
assert((val == '0') || (val == '1') || (val == 'x'));
init_ = val;
}
@ -145,8 +137,8 @@ NetUDP::state_t_* NetUDP::find_state_(const string&str)
return st;
}
NetUDP_COMB::NetUDP_COMB(const string&n, unsigned pins)
: NetNode(n, pins)
NetUDP_COMB::NetUDP_COMB(const string&n, unsigned pins, bool sequ)
: NetNode(n, pins), sequential_(sequ)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name("O", 0);
@ -156,16 +148,17 @@ NetUDP_COMB::NetUDP_COMB(const string&n, unsigned pins)
}
}
void NetUDP_COMB::set_table(const string&input, char output)
bool NetUDP_COMB::set_table(const string&input, char output)
{
assert((output == '0') || (output == '1'));
assert(input.length() == (pin_count()-1));
/* XXXX Need to check to make sure that the input vector
contains a legal combination of characters. In
combinational UDPs, only 0, 1 and x are allowed. */
combinational UDPs, only 0, 1, x, and ? are allowed. */
cm_[input] = output;
return true;
}
void NetUDP_COMB::cleanup_table()
@ -198,6 +191,9 @@ bool NetUDP_COMB::next(string&inp, char&out) const
/*
* $Log: net_udp.cc,v $
* Revision 1.2 2000/11/04 06:36:24 steve
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
*
* Revision 1.1 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.h,v 1.176 2000/10/31 17:49:02 steve Exp $"
#ident "$Id: netlist.h,v 1.177 2000/11/04 06:36:24 steve Exp $"
#endif
/*
@ -1044,11 +1044,52 @@ class NetLogic : public NetNode {
* 1 are listed.
*
*/
class NetUDP : public NetNode {
class NetUDP_COMB : public NetNode {
public:
explicit NetUDP(const string&n, unsigned pins, bool sequ =false);
explicit NetUDP_COMB(const string&n, unsigned pins, bool sequ = false);
virtual bool emit_node(struct target_t*) const;
virtual void dump_node(ostream&, unsigned ind) const;
/* append a new truth table row. */
bool set_table(const string&input, char output);
/* After the primitive is built up, this method is called to
clean up redundancies, and possibly optimize the table. */
void cleanup_table();
/* Use these methods to scan the truth table of the
device. "first" returns the first item in the table, and
"next" returns the next item in the table. The method will
return false when the scan is done. */
bool first(string&inp, char&out) const;
bool next(string&inp, char&out) const;
bool is_sequential() const { return sequential_; }
protected:
// A combinational primitive is more simply represented as a
// simple map of input signals to a single output.
typedef map<string,char> CM_;
CM_ cm_;
private:
bool sequential_;
mutable CM_::const_iterator idx_;
};
class NetUDP : public NetUDP_COMB {
public:
explicit NetUDP(const string&n, unsigned pins, bool sequ = true)
: NetUDP_COMB(n, pins, sequ), init_('x') {};
virtual bool emit_node( struct target_t*) const;
virtual void dump_node(ostream&, unsigned ind) const;
@ -1065,10 +1106,7 @@ class NetUDP : public NetNode {
void set_initial(char);
char get_initial() const { return init_; }
bool is_sequential() const { return sequential_; }
private:
bool sequential_;
char init_;
struct state_t_;
@ -1095,48 +1133,10 @@ class NetUDP : public NetNode {
state_t_*find_state_(const string&);
// A combinational primitive is more simply represented as a
// simple map of input signals to a single output.
typedef map<string,char> CM_;
CM_ cm_;
void dump_sequ_(ostream&o, unsigned ind) const;
void dump_comb_(ostream&o, unsigned ind) const;
};
class NetUDP_COMB : public NetNode {
public:
explicit NetUDP_COMB(const string&n, unsigned pins);
virtual bool emit_node(struct target_t*) const;
virtual void dump_node(ostream&, unsigned ind) const;
/* append a new truth table row. */
void set_table(const string&input, char output);
/* After the primitive is built up, this method is called to
clean up redundancies, and possibly optimize the table. */
void cleanup_table();
/* Use these methods to scan the truth table of the
device. "first" returns the first item in the table, and
"next" returns the next item in the table. The method will
return false when the scan is done. */
bool first(string&inp, char&out) const;
bool next(string&inp, char&out) const;
private:
// A combinational primitive is more simply represented as a
// simple map of input signals to a single output.
map<string,char> cm_;
mutable map<string,char>::const_iterator idx_;
};
/* =========
* A process is a behavioral-model description. A process is a
* statement that may be compound. the various statement types may
@ -2811,6 +2811,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.177 2000/11/04 06:36:24 steve
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
*
* Revision 1.176 2000/10/31 17:49:02 steve
* Support time variables.
*

View File

@ -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.182 2000/10/29 17:10:02 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.183 2000/11/04 06:36:24 steve Exp $"
#endif
# include <iostream>
@ -166,7 +166,6 @@ class target_vvm : public target_t {
virtual bool bufz(const NetBUFZ*);
virtual void udp(const NetUDP*);
virtual void udp_comb(const NetUDP_COMB*);
void udp_sequ_(ostream&os, const NetUDP*);
virtual void net_assign(const NetAssign_*) { }
virtual void net_case_cmp(const NetCaseCmp*);
virtual bool net_cassign(const NetCAssign*);
@ -1922,7 +1921,9 @@ void target_vvm::udp_comb(const NetUDP_COMB*gate)
}
out << " ;" << endl;
out << "static vvm_udp_comb " << mname << "("
out << (gate->is_sequential() ? "static vvm_udp_sequ1 "
: "static vvm_udp_comb " )
<< mname << "("
<< (gate->pin_count()-1) << ", " << mname<<"_ctab);" << endl;
/* Connect the output of the device... */
@ -1945,81 +1946,11 @@ void target_vvm::udp_comb(const NetUDP_COMB*gate)
}
static string state_to_string(unsigned state, unsigned npins)
{
static const char cur_table[3] = { '0', '1', 'x' };
string res = "";
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
char cur = cur_table[state%3];
res = cur + res;
state /= 3;
}
return res;
}
void target_vvm::udp(const NetUDP*gate)
{
assert(gate->is_sequential());
udp_sequ_(out, gate);
}
void target_vvm::udp_sequ_(ostream&os, const NetUDP*gate)
{
assert(gate->pin_count() <= 9);
assert(gate->is_sequential());
unsigned states = 1;
for (unsigned idx = 0 ; idx < gate->pin_count() ; idx += 1)
states *= 3;
os << "static vvm_u32 " << mangle(gate->name()) << "_table[" <<
states << "] = {" << endl;
os << hex;
for (unsigned state = 0 ; state < states ; state += 1) {
string sstr = state_to_string(state, gate->pin_count());
unsigned long entry = 0;
for (unsigned idx = 1 ; idx < sstr.length() ; idx += 1) {
char o[2];
switch (sstr[idx]) {
case '0':
o[0] = '1';
o[1] = 'x';
break;
case '1':
o[0] = '0';
o[1] = 'x';
break;
case 'x':
o[0] = '0';
o[1] = '1';
break;
}
o[0] = gate->table_lookup(sstr, o[0], idx);
o[1] = gate->table_lookup(sstr, o[1], idx);
entry <<= 2;
entry |= (o[0] == '0')? 0 : (o[0] == '1')? 1 : 2;
entry <<= 2;
entry |= (o[1] == '0')? 0 : (o[1] == '1')? 1 : 2;
}
os << " 0x" << setw(8) << setfill('0') << entry << ",";
if (state % 3 == 2)
os << endl;
}
os << "};" << dec << setfill(' ') << endl;
string outfun = defn_gate_outputfun_(os, gate, 0);
os << "static vvm_udp_ssequ<" << gate->pin_count()-1 << "> " <<
mangle(gate->name()) << "(&" << outfun << ", V" <<
gate->get_initial() << ", " << mangle(gate->name()) <<
"_table);" << endl;
/* The UDP output function is much like other logic gates. Use
this general method to output the output function. */
emit_gate_outputfun_(gate, 0);
udp_comb(gate);
}
void target_vvm::net_case_cmp(const NetCaseCmp*gate)
@ -3398,6 +3329,9 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.183 2000/11/04 06:36:24 steve
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
*
* Revision 1.182 2000/10/29 17:10:02 steve
* task threads ned their scope initialized. (PR#32)
*

View File

@ -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.65 2000/09/17 21:26:16 steve Exp $"
#ident "$Id: vvm_gates.h,v 1.66 2000/11/04 06:36:24 steve Exp $"
#endif
# include "vvm.h"
@ -792,74 +792,22 @@ class vvm_udp_comb : public vvm_1bit_out, public vvm_nexus::recvr_t {
void init_I(unsigned idx, vpip_bit_t val);
void start();
private:
protected:
void take_value(unsigned key, vpip_bit_t val);
vpip_bit_t*ibits_;
char*ibits_;
char obit_;
unsigned width_;
const char*table_;
};
/*
* A Sequential UDP has a more complex truth table, and handles
* edges. Pin 0 is an output, and all the remaining pins are
* input. The WIDTH is the number of input pins.
*
* See vvm.txt for a description of the gate transition table.
*/
template <unsigned WIDTH> class vvm_udp_ssequ {
public:
explicit vvm_udp_ssequ(vvm_out_event::action_t o, vpip_bit_t i,
const vvm_u32*tab)
: output_(o), table_(tab)
{ state_[0] = i;
for (unsigned idx = 1; idx < WIDTH+1 ; idx += 1)
state_[idx] = Vx;
}
void init(unsigned pin, vpip_bit_t val)
{ state_[pin] = val; }
void set(unsigned pin, vpip_bit_t val)
{ assert(pin > 0);
assert(pin < WIDTH+1);
if (val == Vz) val = Vx;
if (state_[pin] == val) return;
// Convert the current state into a table index.
unsigned entry = 0;
for (unsigned idx = 0 ; idx < WIDTH+1 ; idx += 1) {
entry *= 3;
entry += state_[idx];
}
// Get the table entry, and the 4bits that encode
// activity on this pin.
vvm_u32 code = table_[entry];
code >>= 4 * (WIDTH-pin);
switch (state_[pin]*4 + val) {
case (V0*4 + V1):
case (V1*4 + V0):
case (Vx*4 + V0):
code = (code>>2) & 3;
break;
case (V0*4 + Vx):
case (V1*4 + Vx):
case (Vx*4 + V1):
code &= 3;
break;
}
// Convert the code to a vpip_bit_t and run with it.
vpip_bit_t outval = (code == 0)? V0 : (code == 1)? V1 : Vx;
state_[0] = outval;
state_[pin] = val;
vvm_event*ev = new vvm_out_event(outval, output_);
ev->schedule(1); // XXXX Delay not supported.
}
private:
vvm_out_event::action_t output_;
const vvm_u32*const table_;
vpip_bit_t state_[WIDTH+1];
class vvm_udp_sequ1 : public vvm_udp_comb
{
public:
explicit vvm_udp_sequ1(unsigned w, const char*t)
: vvm_udp_comb(w+1, t) {};
private:
void take_value(unsigned key, vpip_bit_t val);
};
/*
@ -976,6 +924,9 @@ class vvm_posedge : public vvm_nexus::recvr_t {
/*
* $Log: vvm_gates.h,v $
* Revision 1.66 2000/11/04 06:36:24 steve
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
*
* Revision 1.65 2000/09/17 21:26:16 steve
* Add support for modulus (Eric Aardoom)
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: vvm_udp.cc,v 1.1 2000/03/29 04:37:11 steve Exp $"
#ident "$Id: vvm_udp.cc,v 1.2 2000/11/04 06:36:24 steve Exp $"
#endif
# include "vvm_gates.h"
@ -25,7 +25,8 @@
vvm_udp_comb::vvm_udp_comb(unsigned w, const char*t)
: vvm_1bit_out(0), width_(w), table_(t)
{
ibits_ = new vpip_bit_t[width_];
ibits_ = new char[width_];
obit_ = 'x';
}
vvm_udp_comb::~vvm_udp_comb()
@ -36,54 +37,123 @@ vvm_udp_comb::~vvm_udp_comb()
void vvm_udp_comb::init_I(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[idx] = val;
if (B_IS1(val))
ibits_[idx] = '1';
else if (B_IS0(val))
ibits_[idx] = '0';
else
ibits_[idx] = 'x';
}
void vvm_udp_sequ1::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_ - 1);
ibits_[0] = obit_;
vvm_udp_comb::take_value(key+1, val);
}
void vvm_udp_comb::take_value(unsigned key, vpip_bit_t val)
{
if (ibits_[key] == val)
char old_bit = ibits_[key];
init_I(key, val);
if (ibits_[key] == old_bit)
return;
ibits_[key] = val;
char bit;
if (B_IS1(val))
bit = '1';
else if (B_IS0(val))
bit = '0';
else
bit = 'x';
for (const char*row = table_ ; row[0] ; row += width_+1) {
unsigned idx;
for (idx = 0 ; idx < width_ ; idx += 1)
if (row[idx] != bit)
break;
{
if (row[idx] != ibits_[idx]
&& row[idx] != '?')
{
if (idx == key)
{
char new_bit = ibits_[idx];
switch (row[idx])
{
case '*':
continue;
case '_':
if (new_bit == '0')
continue;
break;
case '+':
if (new_bit == '1')
continue;
break;
case '%':
if (new_bit == 'x')
continue;
break;
case 'r':
if (old_bit=='0' && new_bit=='1')
continue;
break;
case 'R':
if (old_bit=='x' && new_bit=='1')
continue;
break;
case 'f':
if (old_bit=='1' && new_bit=='0')
continue;
break;
case 'F':
if (old_bit=='x' && new_bit=='0')
continue;
break;
case 'P':
if (old_bit=='1' && new_bit=='x')
continue;
break;
case 'N':
if (old_bit=='0' && new_bit=='x')
continue;
break;
}
// bad edge
}
break; // bad edge/level
}
}
if (idx == width_) switch (row[width_]) {
if (idx == width_)
{
if (row[width_] == '-'
|| row[width_] == obit_)
return;
case '0':
output(St0);
return;
case '1':
output(St1);
return;
case 'z':
output(HiZ);
return;
default:
output(StX);
return;
}
obit_ = row[width_];
switch (obit_)
{
case '0':
output(St0);
return;
case '1':
output(St1);
return;
case 'z':
output(HiZ);
return;
default:
output(StX);
return;
}
}
}
output(StX);
obit_ = 'x';
}
/*
* $Log: vvm_udp.cc,v $
* Revision 1.2 2000/11/04 06:36:24 steve
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
*
* Revision 1.1 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*