VVM support for small sequential UDP objects.
This commit is contained in:
parent
10b345bd16
commit
4e2c0036aa
32
netlist.cc
32
netlist.cc
|
|
@ -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)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: netlist.cc,v 1.12 1998/12/14 02:01:35 steve Exp $"
|
#ident "$Id: netlist.cc,v 1.13 1998/12/17 23:54:58 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
|
@ -625,6 +625,33 @@ void NetUDP::cleanup_table()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char NetUDP::table_lookup(const string&from, char to, unsigned pin) const
|
||||||
|
{
|
||||||
|
assert(pin <= pin_count());
|
||||||
|
assert(from.length() == pin_count());
|
||||||
|
FSM_::const_iterator idx = fsm_.find(from);
|
||||||
|
if (idx == fsm_.end())
|
||||||
|
return 'x';
|
||||||
|
|
||||||
|
state_t_*next;
|
||||||
|
switch (to) {
|
||||||
|
case '0':
|
||||||
|
next = (*idx).second->pins[pin].zer;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
next = (*idx).second->pins[pin].one;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
next = (*idx).second->pins[pin].xxx;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next? next->out : 'x';
|
||||||
|
}
|
||||||
|
|
||||||
void NetUDP::set_initial(char val)
|
void NetUDP::set_initial(char val)
|
||||||
{
|
{
|
||||||
assert(sequential_);
|
assert(sequential_);
|
||||||
|
|
@ -784,6 +811,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.cc,v $
|
* $Log: netlist.cc,v $
|
||||||
|
* Revision 1.13 1998/12/17 23:54:58 steve
|
||||||
|
* VVM support for small sequential UDP objects.
|
||||||
|
*
|
||||||
* Revision 1.12 1998/12/14 02:01:35 steve
|
* Revision 1.12 1998/12/14 02:01:35 steve
|
||||||
* Fully elaborate Sequential UDP behavior.
|
* Fully elaborate Sequential UDP behavior.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
11
netlist.h
11
netlist.h
|
|
@ -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)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: netlist.h,v 1.12 1998/12/14 02:01:35 steve Exp $"
|
#ident "$Id: netlist.h,v 1.13 1998/12/17 23:54:58 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -389,7 +389,13 @@ class NetUDP : public NetNode {
|
||||||
bool set_table(const string&input, char output);
|
bool set_table(const string&input, char output);
|
||||||
void cleanup_table();
|
void cleanup_table();
|
||||||
|
|
||||||
|
/* Return the next output from the passed state. Each letter
|
||||||
|
of the input string represents the pin of the same
|
||||||
|
position. */
|
||||||
|
char table_lookup(const string&from, char to, unsigned pin) const;
|
||||||
|
|
||||||
void set_initial(char);
|
void set_initial(char);
|
||||||
|
char get_initial() const { return init_; }
|
||||||
|
|
||||||
bool is_sequential() const { return sequential_; }
|
bool is_sequential() const { return sequential_; }
|
||||||
|
|
||||||
|
|
@ -888,6 +894,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.h,v $
|
* $Log: netlist.h,v $
|
||||||
|
* Revision 1.13 1998/12/17 23:54:58 steve
|
||||||
|
* VVM support for small sequential UDP objects.
|
||||||
|
*
|
||||||
* Revision 1.12 1998/12/14 02:01:35 steve
|
* Revision 1.12 1998/12/14 02:01:35 steve
|
||||||
* Fully elaborate Sequential UDP behavior.
|
* Fully elaborate Sequential UDP behavior.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
76
t-vvm.cc
76
t-vvm.cc
|
|
@ -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)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: t-vvm.cc,v 1.6 1998/11/23 00:20:23 steve Exp $"
|
#ident "$Id: t-vvm.cc,v 1.7 1998/12/17 23:54:58 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
@ -43,6 +43,7 @@ class target_vvm : public target_t {
|
||||||
virtual void signal(ostream&os, const NetNet*);
|
virtual void signal(ostream&os, const NetNet*);
|
||||||
virtual void logic(ostream&os, const NetLogic*);
|
virtual void logic(ostream&os, const NetLogic*);
|
||||||
virtual void bufz(ostream&os, const NetBUFZ*);
|
virtual void bufz(ostream&os, const NetBUFZ*);
|
||||||
|
virtual void udp(ostream&os, const NetUDP*);
|
||||||
virtual void net_const(ostream&os, const NetConst*);
|
virtual void net_const(ostream&os, const NetConst*);
|
||||||
virtual void net_pevent(ostream&os, const NetPEvent*);
|
virtual void net_pevent(ostream&os, const NetPEvent*);
|
||||||
virtual void start_process(ostream&os, const NetProcTop*);
|
virtual void start_process(ostream&os, const NetProcTop*);
|
||||||
|
|
@ -67,6 +68,7 @@ class target_vvm : public target_t {
|
||||||
unsigned indent_;
|
unsigned indent_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This class emits code for the rvalue of a procedural
|
* This class emits code for the rvalue of a procedural
|
||||||
* assignment. The expression is evaluated to fit the width
|
* assignment. The expression is evaluated to fit the width
|
||||||
|
|
@ -378,6 +380,75 @@ void target_vvm::bufz(ostream&os, const NetBUFZ*gate)
|
||||||
emit_gate_outputfun_(gate);
|
emit_gate_outputfun_(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(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;
|
||||||
|
|
||||||
|
os << "static void " << mangle(gate->name()) <<
|
||||||
|
"_output_fun(vvm_simulation*, vvm_bit_t);" << endl;
|
||||||
|
|
||||||
|
os << "static vvm_udp_ssequ<" << gate->pin_count()-1 << "> " <<
|
||||||
|
mangle(gate->name()) << "(&" << mangle(gate->name()) <<
|
||||||
|
"_output_fun, V" << gate->get_initial() << ", " <<
|
||||||
|
mangle(gate->name()) << "_table);" << endl;
|
||||||
|
|
||||||
|
emit_gate_outputfun_(gate);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The NetConst is a synthetic device created to represent constant
|
* The NetConst is a synthetic device created to represent constant
|
||||||
* values. I represent them in the output as a vvm_bufz object that
|
* values. I represent them in the output as a vvm_bufz object that
|
||||||
|
|
@ -671,6 +742,9 @@ extern const struct target tgt_vvm = {
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* $Log: t-vvm.cc,v $
|
* $Log: t-vvm.cc,v $
|
||||||
|
* Revision 1.7 1998/12/17 23:54:58 steve
|
||||||
|
* VVM support for small sequential UDP objects.
|
||||||
|
*
|
||||||
* Revision 1.6 1998/11/23 00:20:23 steve
|
* Revision 1.6 1998/11/23 00:20:23 steve
|
||||||
* NetAssign handles lvalues as pin links
|
* NetAssign handles lvalues as pin links
|
||||||
* instead of a signal pointer,
|
* instead of a signal pointer,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: vvm.h,v 1.2 1998/11/10 00:48:31 steve Exp $"
|
#ident "$Id: vvm.h,v 1.3 1998/12/17 23:54:58 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include <vector>
|
# include <vector>
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
* that executes models that the simulation generator makes.
|
* that executes models that the simulation generator makes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef unsigned vvm_u32;
|
||||||
|
|
||||||
class vvm_event;
|
class vvm_event;
|
||||||
class vvm_simulation;
|
class vvm_simulation;
|
||||||
class vvm_simulation_cycle;
|
class vvm_simulation_cycle;
|
||||||
|
|
@ -215,6 +217,9 @@ class vvm_monitor_t {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: vvm.h,v $
|
* $Log: vvm.h,v $
|
||||||
|
* Revision 1.3 1998/12/17 23:54:58 steve
|
||||||
|
* VVM support for small sequential UDP objects.
|
||||||
|
*
|
||||||
* Revision 1.2 1998/11/10 00:48:31 steve
|
* Revision 1.2 1998/11/10 00:48:31 steve
|
||||||
* Add support it vvm target for level-sensitive
|
* Add support it vvm target for level-sensitive
|
||||||
* triggers (i.e. the Verilog wait).
|
* triggers (i.e. the Verilog wait).
|
||||||
|
|
|
||||||
|
|
@ -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)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: vvm_gates.h,v 1.2 1998/11/10 00:48:31 steve Exp $"
|
#ident "$Id: vvm_gates.h,v 1.3 1998/12/17 23:54:58 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "vvm.h"
|
# include "vvm.h"
|
||||||
|
|
@ -184,6 +184,65 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_xor {
|
||||||
vvm_out_event::action_t output_;
|
vvm_out_event::action_t output_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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, vvm_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 set(vvm_simulation*sim, unsigned pin, vvm_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 vvm_bit_t and run with it.
|
||||||
|
vvm_bit_t outval = (code == 0)? V0 : (code == 1)? V1 : Vx;
|
||||||
|
state_[0] = outval;
|
||||||
|
state_[pin] = val;
|
||||||
|
vvm_event*ev = new vvm_out_event(sim, outval, output_);
|
||||||
|
sim->insert_event(1, ev); // XXXX Delay not supported.
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
vvm_out_event::action_t output_;
|
||||||
|
const vvm_u32*const table_;
|
||||||
|
vvm_bit_t state_[WIDTH+1];
|
||||||
|
};
|
||||||
|
|
||||||
class vvm_bufz {
|
class vvm_bufz {
|
||||||
public:
|
public:
|
||||||
explicit vvm_bufz(vvm_out_event::action_t o)
|
explicit vvm_bufz(vvm_out_event::action_t o)
|
||||||
|
|
@ -219,6 +278,9 @@ class vvm_pevent {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: vvm_gates.h,v $
|
* $Log: vvm_gates.h,v $
|
||||||
|
* Revision 1.3 1998/12/17 23:54:58 steve
|
||||||
|
* VVM support for small sequential UDP objects.
|
||||||
|
*
|
||||||
* Revision 1.2 1998/11/10 00:48:31 steve
|
* Revision 1.2 1998/11/10 00:48:31 steve
|
||||||
* Add support it vvm target for level-sensitive
|
* Add support it vvm target for level-sensitive
|
||||||
* triggers (i.e. the Verilog wait).
|
* triggers (i.e. the Verilog wait).
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue