Fully elaborate Sequential UDP behavior.
This commit is contained in:
parent
45f45f73b7
commit
10b345bd16
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: design_dump.cc,v 1.7 1998/12/07 04:53:17 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.8 1998/12/14 02:01:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -167,9 +167,55 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUDP::dump_node(ostream&o, unsigned ind) const
|
||||
void NetUDP::dump_sequ_(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "UDP: ";
|
||||
string tmp = "";
|
||||
for (unsigned idx = 0 ; idx < ind ; idx += 1)
|
||||
tmp += " ";
|
||||
|
||||
o << tmp << "Sequential UDP" << " #(" << delay1() <<
|
||||
"," << delay2() << "," << delay3() << ") " << name() <<
|
||||
endl;
|
||||
|
||||
for (FSM_::const_iterator ent = fsm_.begin()
|
||||
; ent != fsm_.end() ; ent++) {
|
||||
o << setw(ind+6) << "" << (*ent).first << " -->";
|
||||
|
||||
state_t_*st = (*ent).second;
|
||||
assert((*ent).first[0] == st->out);
|
||||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
string tmp = (*ent).first;
|
||||
if (st->pins[idx].zer) {
|
||||
tmp[0] = st->pins[idx].zer->out;
|
||||
tmp[idx] = '0';
|
||||
o << " " << tmp;
|
||||
}
|
||||
|
||||
if (st->pins[idx].one) {
|
||||
tmp[0] = st->pins[idx].one->out;
|
||||
tmp[idx] = '1';
|
||||
o << " " << tmp;
|
||||
}
|
||||
|
||||
if (st->pins[idx].xxx) {
|
||||
tmp[0] = st->pins[idx].xxx->out;
|
||||
tmp[idx] = 'x';
|
||||
o << " " << tmp;
|
||||
}
|
||||
}
|
||||
|
||||
o << endl;
|
||||
}
|
||||
|
||||
o << setw(ind+6) << "" << "initial value == " << init_ << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUDP::dump_comb_(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinational UDP: ";
|
||||
o << " #(" << delay1() << "," << delay2() << "," << delay3() <<
|
||||
") " << name() << endl;
|
||||
|
||||
|
|
@ -177,6 +223,14 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUDP::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
if (sequential_)
|
||||
dump_sequ_(o, ind);
|
||||
else
|
||||
dump_comb_(o, ind);
|
||||
}
|
||||
|
||||
void NetPEvent::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "event: ";
|
||||
|
|
@ -407,6 +461,9 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.8 1998/12/14 02:01:34 steve
|
||||
* Fully elaborate Sequential UDP behavior.
|
||||
*
|
||||
* Revision 1.7 1998/12/07 04:53:17 steve
|
||||
* Generate OBUF or IBUF attributes (and the gates
|
||||
* to garry them) where a wire is a pad. This involved
|
||||
|
|
|
|||
42
elaborate.cc
42
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: elaborate.cc,v 1.9 1998/12/07 04:53:17 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.10 1998/12/14 02:01:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -255,12 +255,20 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* From a UDP definition in the source, make a NetUDP
|
||||
* object. Elaborate the pin expressions as netlists, then connect
|
||||
* those networks to the pins.
|
||||
*/
|
||||
void PGModule::elaborate_udp_(Design*des, PUdp*udp, const string&path) const
|
||||
{
|
||||
const string my_name = path+"."+get_name();
|
||||
NetUDP*net = new NetUDP(my_name, udp->ports.size());
|
||||
NetUDP*net = new NetUDP(my_name, udp->ports.size(), udp->sequential);
|
||||
net->set_attributes(udp->attributes);
|
||||
|
||||
/* Run through the pins, making netlists for the pin
|
||||
expressions and connecting them to the pin in question. All
|
||||
of this is independent of the nature of the UDP. */
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
if (pin(idx) == 0)
|
||||
continue;
|
||||
|
|
@ -274,10 +282,37 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, const string&path) const
|
|||
|
||||
connect(sig->pin(0), net->pin(idx));
|
||||
|
||||
// Delete excess holding signal.
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(sig))
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
/* Build up the truth table for the netlist from the input
|
||||
strings. */
|
||||
for (unsigned idx = 0 ; idx < udp->tinput.size() ; idx += 1) {
|
||||
string input = udp->sequential
|
||||
? (string("") + udp->tcurrent[idx] + udp->tinput[idx])
|
||||
: udp->tinput[idx];
|
||||
|
||||
net->set_table(input, udp->toutput[idx]);
|
||||
}
|
||||
|
||||
net->cleanup_table();
|
||||
|
||||
if (udp->sequential) switch (udp->initial) {
|
||||
case verinum::V0:
|
||||
net->set_initial('0');
|
||||
break;
|
||||
case verinum::V1:
|
||||
net->set_initial('1');
|
||||
break;
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
net->set_initial('x');
|
||||
break;
|
||||
}
|
||||
|
||||
// All done. Add the object to the design.
|
||||
des->add_node(net);
|
||||
}
|
||||
|
||||
|
|
@ -734,6 +769,9 @@ Design* elaborate(const map<string,Module*>&modules,
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.10 1998/12/14 02:01:34 steve
|
||||
* Fully elaborate Sequential UDP behavior.
|
||||
*
|
||||
* Revision 1.9 1998/12/07 04:53:17 steve
|
||||
* Generate OBUF or IBUF attributes (and the gates
|
||||
* to garry them) where a wire is a pad. This involved
|
||||
|
|
|
|||
210
netlist.cc
210
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: netlist.cc,v 1.11 1998/12/07 04:53:17 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.12 1998/12/14 02:01:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
|
|
@ -423,12 +423,213 @@ NetLogic::NetLogic(const string&n, unsigned pins, TYPE t)
|
|||
pin(idx).set_dir(Link::INPUT);
|
||||
}
|
||||
|
||||
NetUDP::NetUDP(const string&n, unsigned pins)
|
||||
: NetNode(n, pins)
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
NetUDP::state_t_* NetUDP::find_state_(const string&str)
|
||||
{
|
||||
map<string,state_t_*>::iterator cur = fsm_.find(str);
|
||||
if (cur != fsm_.end())
|
||||
return (*cur).second;
|
||||
|
||||
state_t_*st = fsm_[str];
|
||||
if (st == 0) {
|
||||
st = new state_t_(pin_count());
|
||||
st->out = str[0];
|
||||
fsm_[str] = st;
|
||||
}
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method takes the input string, which contains exactly one
|
||||
* edge, and connects it to the correct output state. The output state
|
||||
* will be generated if needed, and the value compared.
|
||||
*/
|
||||
bool NetUDP::set_sequ_(const string&input, char output)
|
||||
{
|
||||
if (output == '-')
|
||||
output = input[0];
|
||||
|
||||
string frm = input;
|
||||
string to = input;
|
||||
to[0] = output;
|
||||
|
||||
unsigned edge = frm.find_first_not_of("01x");
|
||||
assert(frm.find_last_not_of("01x") == edge);
|
||||
|
||||
switch (input[edge]) {
|
||||
case 'r':
|
||||
frm[edge] = '0';
|
||||
to[edge] = '1';
|
||||
break;
|
||||
case 'R':
|
||||
frm[edge] = 'x';
|
||||
to[edge] = '1';
|
||||
break;
|
||||
case 'f':
|
||||
frm[edge] = '1';
|
||||
to[edge] = '0';
|
||||
break;
|
||||
case 'F':
|
||||
frm[edge] = 'x';
|
||||
to[edge] = '0';
|
||||
break;
|
||||
case 'P':
|
||||
frm[edge] = '0';
|
||||
to[edge] = 'x';
|
||||
break;
|
||||
case 'N':
|
||||
frm[edge] = '1';
|
||||
to[edge] = 'x';
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
state_t_*sfrm = find_state_(frm);
|
||||
state_t_*sto = find_state_(to);
|
||||
|
||||
switch (to[edge]) {
|
||||
case '0':
|
||||
assert(sfrm->pins[edge].zer == 0);
|
||||
sfrm->pins[edge].zer = sto;
|
||||
break;
|
||||
case '1':
|
||||
assert(sfrm->pins[edge].one == 0);
|
||||
sfrm->pins[edge].one = sto;
|
||||
break;
|
||||
case 'x':
|
||||
assert(sfrm->pins[edge].xxx == 0);
|
||||
sfrm->pins[edge].xxx = sto;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetUDP::sequ_glob_(string input, char output)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < input.length() ; idx += 1)
|
||||
switch (input[idx]) {
|
||||
case '0':
|
||||
case '1':
|
||||
case 'x':
|
||||
case 'r':
|
||||
case 'R':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'P':
|
||||
case 'N':
|
||||
break;
|
||||
|
||||
case '?': // Iterate over all the levels
|
||||
input[idx] = '0';
|
||||
sequ_glob_(input, output);
|
||||
input[idx] = '1';
|
||||
sequ_glob_(input, output);
|
||||
input[idx] = 'x';
|
||||
sequ_glob_(input, output);
|
||||
return true;
|
||||
|
||||
case '*': // Iterate over all the edges
|
||||
input[idx] = 'r';
|
||||
sequ_glob_(input, output);
|
||||
input[idx] = 'R';
|
||||
sequ_glob_(input, output);
|
||||
input[idx] = 'f';
|
||||
sequ_glob_(input, output);
|
||||
input[idx] = 'F';
|
||||
sequ_glob_(input, output);
|
||||
input[idx] = 'P';
|
||||
sequ_glob_(input, output);
|
||||
input[idx] = 'N';
|
||||
sequ_glob_(input, output);
|
||||
return true;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return set_sequ_(input, output);
|
||||
}
|
||||
|
||||
bool NetUDP::set_table(const string&input, char output)
|
||||
{
|
||||
assert((output == '0') || (output == '1') || (sequential_ &&
|
||||
(output == '-')));
|
||||
|
||||
if (sequential_) {
|
||||
assert(input.length() == pin_count());
|
||||
/* XXXX Need to check to make sure that the input vector
|
||||
contains a legal combination of characters. */
|
||||
return sequ_glob_(input, output);
|
||||
|
||||
} else {
|
||||
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. */
|
||||
assert(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void NetUDP::cleanup_table()
|
||||
{
|
||||
for (FSM_::iterator idx = fsm_.begin() ; idx != fsm_.end() ; idx++) {
|
||||
string str = (*idx).first;
|
||||
state_t_*st = (*idx).second;
|
||||
assert(str[0] == st->out);
|
||||
|
||||
for (unsigned pin = 0 ; pin < pin_count() ; pin += 1) {
|
||||
if (st->pins[pin].zer && st->pins[pin].zer->out == 'x')
|
||||
st->pins[pin].zer = 0;
|
||||
if (st->pins[pin].one && st->pins[pin].one->out == 'x')
|
||||
st->pins[pin].one = 0;
|
||||
if (st->pins[pin].xxx && st->pins[pin].xxx->out == 'x')
|
||||
st->pins[pin].xxx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (FSM_::iterator idx = fsm_.begin() ; idx != fsm_.end() ; ) {
|
||||
FSM_::iterator cur = idx;
|
||||
idx ++;
|
||||
|
||||
state_t_*st = (*cur).second;
|
||||
|
||||
if (st->out != 'x')
|
||||
continue;
|
||||
|
||||
for (unsigned pin = 0 ; pin < pin_count() ; pin += 1) {
|
||||
if (st->pins[pin].zer)
|
||||
goto break_label;
|
||||
if (st->pins[pin].one)
|
||||
goto break_label;
|
||||
if (st->pins[pin].xxx)
|
||||
goto break_label;
|
||||
}
|
||||
|
||||
//delete st;
|
||||
fsm_.erase(cur);
|
||||
|
||||
break_label:;
|
||||
}
|
||||
}
|
||||
|
||||
void NetUDP::set_initial(char val)
|
||||
{
|
||||
assert(sequential_);
|
||||
assert((val == '0') || (val == '1') || (val == 'x'));
|
||||
init_ = val;
|
||||
}
|
||||
|
||||
string Design::get_flag(const string&key) const
|
||||
|
|
@ -583,6 +784,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.12 1998/12/14 02:01:35 steve
|
||||
* Fully elaborate Sequential UDP behavior.
|
||||
*
|
||||
* Revision 1.11 1998/12/07 04:53:17 steve
|
||||
* Generate OBUF or IBUF attributes (and the gates
|
||||
* to garry them) where a wire is a pad. This involved
|
||||
|
|
|
|||
84
netlist.h
84
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: netlist.h,v 1.11 1998/12/07 04:53:17 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.12 1998/12/14 02:01:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -338,14 +338,91 @@ class NetLogic : public NetNode {
|
|||
* The UDP is a User Defined Primitive from the Verilog source. Do not
|
||||
* expand it out any further then this in the netlist, as this can be
|
||||
* used to represent target device primitives.
|
||||
*
|
||||
* The UDP can be combinational or sequential. The sequentianl UDP
|
||||
* includes the current output in the truth table, and supports edges,
|
||||
* whereas the combinational does not and is entirely level sensitive.
|
||||
* In any case, pin 0 is an output, and all the remaining pins are
|
||||
* inputs.
|
||||
*
|
||||
* The truth table is canonically represented as a finite state
|
||||
* machine with the current state representing the inputs and the
|
||||
* current output, and the next state carrying the new output value to
|
||||
* use. All the outgoing transitions from a state represent a single
|
||||
* edge.
|
||||
*
|
||||
* Set_table takes as input a string with one letter per pin. The
|
||||
* valid characters are:
|
||||
*
|
||||
* 0, 1, x -- The levels
|
||||
* r -- (01)
|
||||
* R -- (x1)
|
||||
* f -- (10)
|
||||
* F -- (x0)
|
||||
* P -- (0x)
|
||||
* N -- (1x)
|
||||
*
|
||||
* COMBINATIONAL
|
||||
* The logic table is a map between the input levels and the
|
||||
* output. Each input pin can have the value 0, 1 or x and the output
|
||||
* can have the values 0 or 1. If the input matches nothing, the
|
||||
* output is x. In canonical form, only the entries that generate 0 or
|
||||
* 1 are listed.
|
||||
*
|
||||
* SEQUENTIAL
|
||||
* These objects have a single bit of memory. The logic table includes
|
||||
* an entry for the current value, and allows edges on the inputs. In
|
||||
* canonical form, inly then entries that generate 0, 1 or - (no change)
|
||||
* are listed.
|
||||
*
|
||||
*/
|
||||
class NetUDP : public NetNode {
|
||||
|
||||
public:
|
||||
explicit NetUDP(const string&n, unsigned pins);
|
||||
explicit NetUDP(const string&n, unsigned pins, bool sequ =false);
|
||||
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
|
||||
/* return false if the entry conflicts with an existing
|
||||
entry. In any case, the new output overrides. */
|
||||
bool set_table(const string&input, char output);
|
||||
void cleanup_table();
|
||||
|
||||
void set_initial(char);
|
||||
|
||||
bool is_sequential() const { return sequential_; }
|
||||
|
||||
private:
|
||||
const bool sequential_;
|
||||
char init_;
|
||||
|
||||
struct state_t_;
|
||||
struct pin_t_ {
|
||||
state_t_*zer;
|
||||
state_t_*one;
|
||||
state_t_*xxx;
|
||||
|
||||
explicit pin_t_() : zer(0), one(0), xxx(0) { }
|
||||
};
|
||||
|
||||
struct state_t_ {
|
||||
char out;
|
||||
pin_t_*pins;
|
||||
|
||||
state_t_(unsigned n) : out(0), pins(new pin_t_[n]) {}
|
||||
~state_t_() { delete[]pins; }
|
||||
};
|
||||
|
||||
typedef map<string,state_t_*> FSM_;
|
||||
FSM_ fsm_;
|
||||
bool set_sequ_(const string&in, char out);
|
||||
bool sequ_glob_(string, char out);
|
||||
|
||||
state_t_*find_state_(const string&);
|
||||
|
||||
void dump_sequ_(ostream&o, unsigned ind) const;
|
||||
void dump_comb_(ostream&o, unsigned ind) const;
|
||||
};
|
||||
|
||||
/* =========
|
||||
|
|
@ -811,6 +888,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.12 1998/12/14 02:01:35 steve
|
||||
* Fully elaborate Sequential UDP behavior.
|
||||
*
|
||||
* Revision 1.11 1998/12/07 04:53:17 steve
|
||||
* Generate OBUF or IBUF attributes (and the gates
|
||||
* to garry them) where a wire is a pad. This involved
|
||||
|
|
|
|||
4
parse.y
4
parse.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: parse.y,v 1.8 1998/12/01 00:42:14 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.9 1998/12/14 02:01:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -730,7 +730,7 @@ udp_input_sym
|
|||
| 'b' { $$ = 'b'; }
|
||||
| '*' { $$ = '*'; }
|
||||
| 'f' { $$ = 'f'; }
|
||||
| 'r' { $$ = 'f'; }
|
||||
| 'r' { $$ = 'r'; }
|
||||
;
|
||||
|
||||
udp_output_sym
|
||||
|
|
|
|||
Loading…
Reference in New Issue