New and improved combinational primitives.

This commit is contained in:
steve 2000-03-29 04:37:10 +00:00
parent 995f7e89d1
commit d97ab9be23
14 changed files with 544 additions and 185 deletions

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.40 2000/03/21 05:08:32 steve Exp $"
#ident "$Id: Makefile.in,v 1.41 2000/03/29 04:37:10 steve Exp $"
#
#
SHELL = /bin/sh
@ -72,7 +72,7 @@ FF = nobufz.o nodangle.o propinit.o synth.o xnfio.o xnfsyn.o
O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
elab_net.o elab_pexpr.o elab_scope.o emit.o eval.o eval_tree.o \
expr_synth.o functor.o lexor.o lexor_keyword.o mangle.o netlist.o \
net_design.o nexus_from_link.o pad_to_width.o \
net_design.o net_udp.o nexus_from_link.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.o \
verinum.o verireal.o target.o targets.o Module.o PDelays.o PExpr.o PGate.o \

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: PGate.h,v 1.15 2000/03/08 04:36:53 steve Exp $"
#ident "$Id: PGate.h,v 1.16 2000/03/29 04:37:10 steve Exp $"
#endif
# include "svector.h"
@ -194,12 +194,16 @@ class PGModule : public PGate {
PExpr*lsb_;
void elaborate_mod_(Design*, Module*mod, const string&path) const;
void elaborate_udp_(Design*, PUdp *udp, const string&path) const;
void elaborate_sudp_(Design*, PUdp *udp, const string&path) const;
void elaborate_cudp_(Design*, PUdp *udp, const string&path) const;
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
};
/*
* $Log: PGate.h,v $
* Revision 1.16 2000/03/29 04:37:10 steve
* New and improved combinational primitives.
*
* Revision 1.15 2000/03/08 04:36:53 steve
* Redesign the implementation of scopes and parameters.
* I now generate the scopes and notice the parameters

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.69 2000/03/12 17:09:40 steve Exp $"
#ident "$Id: design_dump.cc,v 1.70 2000/03/29 04:37:10 steve Exp $"
#endif
/*
@ -336,18 +336,7 @@ void NetUDP::dump_sequ_(ostream&o, unsigned ind) const
void NetUDP::dump_comb_(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinational UDP: ";
o << " #(" << rise_time() << "," << fall_time() << "," << decay_time() <<
") " << name() << endl;
for (CM_::const_iterator ent = cm_.begin()
; ent != cm_.end() ; ent++) {
o << setw(ind+6) << "" << (*ent).first << " --> " <<
(*ent).second << endl;
}
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
assert(0);
}
void NetUDP::dump_node(ostream&o, unsigned ind) const
@ -358,6 +347,22 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const
dump_comb_(o, ind);
}
void NetUDP_COMB::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinational primitive: ";
o << " #(" << rise_time() << "," << fall_time() << "," << decay_time() <<
") " << name() << endl;
for (map<string,char>::const_iterator ent = cm_.begin()
; ent != cm_.end() ; ent++) {
o << setw(ind+6) << "" << (*ent).first << " --> " <<
(*ent).second << endl;
}
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetNEvent::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "event: ";
@ -892,6 +897,9 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.70 2000/03/29 04:37:10 steve
* New and improved combinational primitives.
*
* Revision 1.69 2000/03/12 17:09:40 steve
* Support localparam.
*

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: elaborate.cc,v 1.150 2000/03/20 15:28:58 steve Exp $"
#ident "$Id: elaborate.cc,v 1.151 2000/03/29 04:37:11 steve Exp $"
#endif
/*
@ -535,12 +535,53 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const
}
}
void PGModule::elaborate_cudp_(Design*des, PUdp*udp, const string&path) const
{
const string my_name = path+"."+get_name();
NetUDP_COMB*net = new NetUDP_COMB(my_name, udp->ports.count());
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;
NetNet*sig = pin(idx)->elaborate_net(des, path, 1, 0, 0, 0);
if (sig == 0) {
cerr << "internal error: Expression too complicated "
"for elaboration:" << *pin(idx) << endl;
continue;
}
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.count() ; idx += 1) {
string input = udp->tinput[idx];
net->set_table(input, udp->toutput[idx]);
}
net->cleanup_table();
// All done. Add the object to the design.
des->add_node(net);
}
/*
* 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
void PGModule::elaborate_sudp_(Design*des, PUdp*udp, const string&path) const
{
const string my_name = path+"."+get_name();
NetUDP*net = new NetUDP(my_name, udp->ports.count(), udp->sequential);
@ -570,16 +611,13 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, const string&path) const
/* Build up the truth table for the netlist from the input
strings. */
for (unsigned idx = 0 ; idx < udp->tinput.count() ; idx += 1) {
string input = udp->sequential
? (string("") + udp->tcurrent[idx] + udp->tinput[idx])
: udp->tinput[idx];
string input = string("") + udp->tcurrent[idx] + udp->tinput[idx];
net->set_table(input, udp->toutput[idx]);
}
net->cleanup_table();
if (udp->sequential) switch (udp->initial) {
switch (udp->initial) {
case verinum::V0:
net->set_initial('0');
break;
@ -608,7 +646,10 @@ void PGModule::elaborate(Design*des, const string&path) const
// Try a primitive type
map<string,PUdp*>::const_iterator udp = udplist->find(type_);
if (udp != udplist->end()) {
elaborate_udp_(des, (*udp).second, path);
if ((*udp).second->sequential)
elaborate_sudp_(des, (*udp).second, path);
else
elaborate_cudp_(des, (*udp).second, path);
return;
}
@ -1962,6 +2003,9 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.151 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
* Revision 1.150 2000/03/20 15:28:58 steve
* Fix lval part select of non-blocking assign.
*

10
emit.cc
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: emit.cc,v 1.34 2000/03/08 04:36:53 steve Exp $"
#ident "$Id: emit.cc,v 1.35 2000/03/29 04:37:11 steve Exp $"
#endif
/*
@ -40,6 +40,11 @@ void NetLogic::emit_node(ostream&o, struct target_t*tgt) const
tgt->logic(o, this);
}
void NetUDP_COMB::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->udp_comb(o, this);
}
void NetUDP::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->udp(o, this);
@ -397,6 +402,9 @@ bool emit(ostream&o, const Design*des, const char*type)
/*
* $Log: emit.cc,v $
* Revision 1.35 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
* Revision 1.34 2000/03/08 04:36:53 steve
* Redesign the implementation of scopes and parameters.
* I now generate the scopes and notice the parameters

205
net_udp.cc Normal file
View File

@ -0,0 +1,205 @@
/*
* 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: net_udp.cc,v 1.1 2000/03/29 04:37:11 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 == '-')));
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. */
cm_[input] = output;
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:;
}
}
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)
{
assert(sequential_);
assert((val == '0') || (val == '1') || (val == 'x'));
init_ = val;
}
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;
}
NetUDP_COMB::NetUDP_COMB(const string&n, unsigned pins)
: NetNode(n, pins)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name("O", 0);
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name("I", idx-1);
}
}
void 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. */
cm_[input] = output;
}
void NetUDP_COMB::cleanup_table()
{
}
bool NetUDP_COMB::first(string&inp, char&out) const
{
idx_ = cm_.begin();
if (idx_ == cm_.end())
return false;
inp = (*idx_).first;
out = (*idx_).second;
return true;
}
bool NetUDP_COMB::next(string&inp, char&out) const
{
idx_ ++;
if (idx_ == cm_.end())
return false;
inp = (*idx_).first;
out = (*idx_).second;
return true;
}
/*
* $Log: net_udp.cc,v $
* Revision 1.1 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
*/

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: netlist.cc,v 1.108 2000/03/12 17:09:41 steve Exp $"
#ident "$Id: netlist.cc,v 1.109 2000/03/29 04:37:11 steve Exp $"
#endif
# include <cassert>
@ -2374,31 +2374,6 @@ NetNet* NetTaskDef::port(unsigned idx)
return ports_[idx];
}
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
@ -2546,106 +2521,11 @@ bool NetUDP::sequ_glob_(string input, char output)
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. */
cm_[input] = output;
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:;
}
}
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)
{
assert(sequential_);
assert((val == '0') || (val == '1') || (val == 'x'));
init_ = val;
}
/*
* $Log: netlist.cc,v $
* Revision 1.109 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
* Revision 1.108 2000/03/12 17:09:41 steve
* Support localparam.
*
@ -2670,33 +2550,5 @@ void NetUDP::set_initial(char val)
*
* Revision 1.102 1999/12/30 04:19:12 steve
* Propogate constant 0 in low bits of adders.
*
* Revision 1.101 1999/12/17 03:38:46 steve
* NetConst can now hold wide constants.
*
* Revision 1.100 1999/12/16 02:42:15 steve
* Simulate carry output on adders.
*
* Revision 1.99 1999/12/05 19:30:43 steve
* Generate XNF RAMS from synthesized memories.
*
* Revision 1.98 1999/12/05 02:24:09 steve
* Synthesize LPM_RAM_DQ for writes into memories.
*
* Revision 1.97 1999/12/02 16:58:58 steve
* Update case comparison (Eric Aardoom).
*
* Revision 1.96 1999/11/28 23:42:02 steve
* NetESignal object no longer need to be NetNode
* objects. Let them keep a pointer to NetNet objects.
*
* Revision 1.95 1999/11/28 01:16:18 steve
* gate outputs need to set signal values.
*
* Revision 1.94 1999/11/27 19:07:57 steve
* Support the creation of scopes.
*
* Revision 1.93 1999/11/24 04:01:59 steve
* Detect and list scope names.
*/

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.114 2000/03/12 17:09:41 steve Exp $"
#ident "$Id: netlist.h,v 1.115 2000/03/29 04:37:11 steve Exp $"
#endif
/*
@ -919,6 +919,39 @@ class NetUDP : public NetNode {
void dump_comb_(ostream&o, unsigned ind) const;
};
class NetUDP_COMB : public NetNode {
public:
explicit NetUDP_COMB(const string&n, unsigned pins);
virtual void emit_node(ostream&, 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
@ -2195,6 +2228,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.115 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
* Revision 1.114 2000/03/12 17:09:41 steve
* Support localparam.
*

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.126 2000/03/26 16:28:31 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.127 2000/03/29 04:37:11 steve Exp $"
#endif
# include <iostream>
@ -73,6 +73,8 @@ class target_vvm : public target_t {
virtual void logic(ostream&os, const NetLogic*);
virtual void bufz(ostream&os, const NetBUFZ*);
virtual void udp(ostream&os, const NetUDP*);
virtual void udp_comb(ostream&os, const NetUDP_COMB*);
void udp_sequ_(ostream&os, const NetUDP*);
virtual void net_assign_nb(ostream&os, const NetAssignNB*);
virtual void net_case_cmp(ostream&os, const NetCaseCmp*);
virtual void net_const(ostream&os, const NetConst*);
@ -1527,6 +1529,47 @@ void target_vvm::bufz(ostream&os, const NetBUFZ*gate)
}
void target_vvm::udp_comb(ostream&os, const NetUDP_COMB*gate)
{
string mname = mangle(gate->name());
string nexus;
unsigned ncode;
os << "static const char*" << mname << "_ctab =" << endl;
string inp;
char out;
for (bool rc = gate->first(inp, out)
; rc ; rc = gate->next(inp,out)) {
os << " \"" << inp << out << "\"" << endl;
}
os << " ;" << endl;
os << "static vvm_udp_comb " << mname << "("
<< (gate->pin_count()-1) << ", " << mname<<"_ctab);" << endl;
/* Connect the output of the device... */
nexus = nexus_from_link(&gate->pin(0));
ncode = nexus_wire_map[nexus];
init_code << " nexus_wire_table["<<ncode<<"].connect(&" <<
mname << ");" << endl;
/* Connect the inputs of the device... */
for (unsigned idx = 1 ; idx < gate->pin_count() ; idx += 1) {
if (! gate->pin(idx).is_linked())
continue;
nexus = nexus_from_link(&gate->pin(idx));
ncode = nexus_wire_map[nexus];
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << "," << (idx-1) << ");" << endl;
}
}
static string state_to_string(unsigned state, unsigned npins)
{
static const char cur_table[3] = { '0', '1', 'x' };
@ -1541,6 +1584,12 @@ static string state_to_string(unsigned state, unsigned npins)
}
void target_vvm::udp(ostream&os, const NetUDP*gate)
{
assert(gate->is_sequential());
udp_sequ_(os, gate);
}
void target_vvm::udp_sequ_(ostream&os, const NetUDP*gate)
{
assert(gate->pin_count() <= 9);
assert(gate->is_sequential());
@ -2440,6 +2489,9 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.127 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
* Revision 1.126 2000/03/26 16:28:31 steve
* vvm_bitset_t is no longer a template.
*

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: target.cc,v 1.30 2000/02/23 02:56:56 steve Exp $"
#ident "$Id: target.cc,v 1.31 2000/03/29 04:37:11 steve Exp $"
#endif
# include "target.h"
@ -73,6 +73,12 @@ void target_t::udp(ostream&os, const NetUDP*)
"Unhandled UDP." << endl;
}
void target_t::udp_comb(ostream&os, const NetUDP_COMB*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled combinational primitive." << endl;
}
void target_t::lpm_add_sub(ostream&, const NetAddSub*)
{
cerr << "target (" << typeid(*this).name() << "): "
@ -314,6 +320,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* Revision 1.31 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
* Revision 1.30 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*

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: target.h,v 1.29 2000/02/23 02:56:56 steve Exp $"
#ident "$Id: target.h,v 1.30 2000/03/29 04:37:11 steve Exp $"
#endif
# include "netlist.h"
@ -82,6 +82,7 @@ struct target_t {
virtual void logic(ostream&os, const NetLogic*);
virtual void bufz(ostream&os, const NetBUFZ*);
virtual void udp(ostream&os, const NetUDP*);
virtual void udp_comb(ostream&os, const NetUDP_COMB*);
virtual void net_assign(ostream&os, const NetAssign*);
virtual void net_assign_nb(ostream&os, const NetAssignNB*);
virtual void net_case_cmp(ostream&os, const NetCaseCmp*);
@ -147,6 +148,9 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* Revision 1.30 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
* Revision 1.29 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.26 2000/03/22 05:16:38 steve Exp $"
#ident "$Id: Makefile.in,v 1.27 2000/03/29 04:37:11 steve Exp $"
#
#
SHELL = /bin/sh
@ -61,7 +61,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_ff.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 vvm_udp.o vpip.o
P = vpi_bit.o vpi_callback.o \
vpi_const.o vpi_iter.o vpi_memory.o vpi_null.o \

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.52 2000/03/26 16:28:31 steve Exp $"
#ident "$Id: vvm_gates.h,v 1.53 2000/03/29 04:37:11 steve Exp $"
#endif
# include "vvm.h"
@ -640,6 +640,49 @@ class vvm_eeq : public vvm_1bit_out, public vvm_nexus::recvr_t {
vpip_bit_t input_[2];
};
/*
* This class allows programmers to define combinational primitives at
* truth tables. The device has a single bit output, and any fixed
* width.
*
* The truth table is specified as a string of characters organized as
* a table. Every width+1 characters represents one row, including the
* set of inputs and the output that they generated. There can be any
* number of rows in the table, which is terminated by a nul byte. The
* table is passed to the constructor as a constant string.
*
* This is a simple example of a truth table for an inverter. The
* width is 1, so there are two characters in each row. The last
* character in each row is the output if all the other characters in
* the row match the input. As you can see, this table inverts its
* input and outputs 'x' if the input is unknown.
*
* const char*invert_table =
* "01"
* "10"
* "xx";
*
* The valid input characters are '0', '1' and 'x'. The valid output
* characters are '0', '1', 'x' and 'z'. (The last is not supported by
* Verilog primitives, so ivl will never generate it.)
*/
class vvm_udp_comb : public vvm_1bit_out, public vvm_nexus::recvr_t {
public:
explicit vvm_udp_comb(unsigned w, const char*t);
~vvm_udp_comb();
void init_I(unsigned idx, vpip_bit_t val);
void start();
private:
void take_value(unsigned key, vpip_bit_t val);
vpip_bit_t*ibits_;
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
@ -796,6 +839,9 @@ template <unsigned WIDTH> class vvm_pevent : public vvm_nexus::recvr_t {
/*
* $Log: vvm_gates.h,v $
* Revision 1.53 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
* Revision 1.52 2000/03/26 16:28:31 steve
* vvm_bitset_t is no longer a template.
*

91
vvm/vvm_udp.cc Normal file
View File

@ -0,0 +1,91 @@
/*
* 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_udp.cc,v 1.1 2000/03/29 04:37:11 steve Exp $"
#endif
# include "vvm_gates.h"
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_];
}
vvm_udp_comb::~vvm_udp_comb()
{
delete[]ibits_;
}
void vvm_udp_comb::init_I(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[idx] = val;
}
void vvm_udp_comb::take_value(unsigned key, vpip_bit_t val)
{
if (ibits_[key] == val)
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 (idx == width_) switch (row[width_]) {
case '0':
output(St0);
return;
case '1':
output(St1);
return;
case 'z':
output(HiZ);
return;
default:
output(StX);
return;
}
}
output(StX);
}
/*
* $Log: vvm_udp.cc,v $
* Revision 1.1 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
*/