mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 06:16:47 +02:00
Compare commits
88
Commits
version0_1
...
v0_2rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59c240bc9b | ||
|
|
d751b05cec | ||
|
|
843af31958 | ||
|
|
5aea537ab9 | ||
|
|
b734ecf02f | ||
|
|
5b52c384d6 | ||
|
|
2cba0a50f3 | ||
|
|
b354cf68b8 | ||
|
|
a9264d71c6 | ||
|
|
e0873f6c14 | ||
|
|
b8ddbcf62b | ||
|
|
bd09bed662 | ||
|
|
1ee4015aa8 | ||
|
|
a8d787bd66 | ||
|
|
e77bcf6910 | ||
|
|
2bc8f79e0f | ||
|
|
e58be1b128 | ||
|
|
ee180f6cf0 | ||
|
|
ce0b97a8f0 | ||
|
|
cf8d17a6ab | ||
|
|
e6bd088984 | ||
|
|
9b3c3b6e7a | ||
|
|
dc5bd8ea59 | ||
|
|
121b6c2ecb | ||
|
|
57d28e4f86 | ||
|
|
d84b72609d | ||
|
|
ef98be1192 | ||
|
|
3b9dedbc86 | ||
|
|
aa8908c52f | ||
|
|
3d1ffced57 | ||
|
|
f37f69f160 | ||
|
|
fac3bde2c8 | ||
|
|
9125a4c451 | ||
|
|
bed47a4ab4 | ||
|
|
2de887c2ff | ||
|
|
fdf2c1b0d0 | ||
|
|
7f78b9bf56 | ||
|
|
d6f53b2582 | ||
|
|
848110bc33 | ||
|
|
eb4cdc5026 | ||
|
|
3d673c1f02 | ||
|
|
a48b4c4f8d | ||
|
|
ba7fdb580d | ||
|
|
9e5ff89ef3 | ||
|
|
0d5e4b40d0 | ||
|
|
142b9e667d | ||
|
|
f3b76d958d | ||
|
|
87d6df5204 | ||
|
|
c7193fa6fe | ||
|
|
645c24289e | ||
|
|
e52a5be16e | ||
|
|
7e37b61a05 | ||
|
|
cbd353fbb8 | ||
|
|
4c274223cf | ||
|
|
65e4e9f428 | ||
|
|
e6820ed169 | ||
|
|
c3cb0f2371 | ||
|
|
31f1ceea9f | ||
|
|
94afe54741 | ||
|
|
080f161c37 | ||
|
|
5ce35e3e60 | ||
|
|
6d0edcf58a | ||
|
|
7033836e01 | ||
|
|
b7409d98ff | ||
|
|
b6d1bb1fa7 | ||
|
|
4558a7d8d0 | ||
|
|
22c2625ace | ||
|
|
4de8ba489d | ||
|
|
65ae92859c | ||
|
|
d355270c2d | ||
|
|
ced7cc6d60 | ||
|
|
d54cc14ca2 | ||
|
|
98a57f4fac | ||
|
|
40ca71b10b | ||
|
|
e7e58cdd71 | ||
|
|
1dcf9de34c | ||
|
|
fcb1d8dc72 | ||
|
|
5fa7e1c31b | ||
|
|
6e3c258edb | ||
|
|
6be5421c8a | ||
|
|
76655ce2bb | ||
|
|
3e1738dcec | ||
|
|
ec8dec74a6 | ||
|
|
838d25890b | ||
|
|
4a6d3a5104 | ||
|
|
b688cdbc40 | ||
|
|
09de918198 | ||
|
|
3e2bb85f58 |
@@ -7,6 +7,7 @@ dep
|
||||
configure
|
||||
Makefile
|
||||
verilog
|
||||
gverilog
|
||||
config.status
|
||||
config.log
|
||||
config.cache
|
||||
|
||||
+5
-2
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: LineInfo.h,v 1.3 1999/02/15 02:06:15 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: LineInfo.h,v 1.4 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cstdio>
|
||||
@@ -50,6 +50,9 @@ class LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.4 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/02/15 02:06:15 steve
|
||||
* Elaborate gate ranges.
|
||||
*
|
||||
|
||||
+19
-11
@@ -18,12 +18,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.30 1999/11/29 17:02:21 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.36 2000/02/05 06:40:35 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
VERSION = 0.2PRE
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -39,6 +39,7 @@ includedir = $(prefix)/include
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
STRIP = @STRIP@
|
||||
@@ -47,7 +48,7 @@ CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CXXFLAGS = @CXXFLAGS@ -I$(srcdir)
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: ivl verilog
|
||||
all: ivl verilog gverilog
|
||||
cd vpi ; $(MAKE) all
|
||||
cd vvm ; $(MAKE) all
|
||||
cd ivlpp ; $(MAKE) all
|
||||
@@ -66,7 +67,7 @@ distclean: clean
|
||||
rm -f Makefile
|
||||
|
||||
TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
|
||||
FF = nobufz.o nodangle.o propinit.o sigfold.o synth.o xnfio.o xnfsyn.o
|
||||
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 emit.o eval.o eval_tree.o expr_synth.o functor.o \
|
||||
@@ -91,11 +92,15 @@ verilog: $(srcdir)/verilog.sh
|
||||
sed -e 's;@$(tmp1)@;@bindir@;' \
|
||||
-e 's;@$(tmp2)@;@libdir@;' \
|
||||
-e 's;@$(tmp3)@;@includedir@;' \
|
||||
-e 's;@dllib@;@DLLIB@;' \
|
||||
-e 's;@$(tmp4)@;@CXX@;' < $< > $@
|
||||
|
||||
ivl: $O
|
||||
$(CXX) $(CXXFLAGS) -o ivl $O
|
||||
|
||||
gverilog: gverilog.c
|
||||
$(CC) $(CPPFLAGS) -o gverilog -DLIBDIR='"@libdir@"' -DINCDIR='"@includedir@"' gverilog.c
|
||||
|
||||
%.o dep/%.d: %.cc
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
@@ -113,26 +118,29 @@ parse.h parse.cc: $(srcdir)/parse.y
|
||||
lexor.cc: $(srcdir)/lexor.lex
|
||||
flex -PVL -s -olexor.cc $(srcdir)/lexor.lex
|
||||
|
||||
install: all installdirs $(bindir)/verilog $(bindir)/ivl $(mandir)/man1/verilog.1
|
||||
install: all installdirs $(bindir)/verilog $(bindir)/gverilog $(libdir)/ivl/ivl $(mandir)/man1/verilog.1
|
||||
cd vpi ; $(MAKE) install
|
||||
cd vvm ; $(MAKE) install
|
||||
cd ivlpp ; $(MAKE) install
|
||||
|
||||
$(bindir)/verilog: ./verilog
|
||||
$(INSTALL_PROGRAM) ./verilog $(bindir)/verilog
|
||||
$(INSTALL_SCRIPT) ./verilog $(bindir)/verilog
|
||||
|
||||
$(bindir)/ivl: ivl
|
||||
$(INSTALL_PROGRAM) ./ivl $(bindir)/ivl
|
||||
$(STRIP) $(bindir)/ivl
|
||||
$(bindir)/gverilog: ./gverilog
|
||||
$(INSTALL_PROGRAM) ./gverilog $(bindir)/gverilog
|
||||
|
||||
$(libdir)/ivl/ivl: ./ivl
|
||||
$(INSTALL_PROGRAM) ./ivl $(libdir)/ivl/ivl
|
||||
$(STRIP) $(libdir)/ivl/ivl
|
||||
|
||||
$(mandir)/man1/verilog.1: $(srcdir)/verilog.1
|
||||
$(INSTALL_DATA) $(srcdir)/verilog.1 $(mandir)/man1/verilog.1
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(mandir)/man1
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(libdir)/ivl $(mandir)/man1
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/ivl
|
||||
rm -f $(libdir)/ivl/ivl
|
||||
rm -f $(bindir)/verilog
|
||||
rm -f $(mandir)/man1/verilog.1
|
||||
cd vpi ; $(MAKE) uninstall
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,24 +16,38 @@
|
||||
* 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)
|
||||
#ident "$Id: Module.cc,v 1.7 1999/09/17 02:06:25 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Module.cc,v 1.10 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "Module.h"
|
||||
# include "PGate.h"
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
Module::Module(const string&name, const svector<Module::port_t*>*pp)
|
||||
: name_(name)
|
||||
{
|
||||
if (pp) {
|
||||
// Save the list of ports, then scan the list to make
|
||||
// the implicit wires. Add those wires to the wire map.
|
||||
ports_ = *pp;
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
port_t*cur = ports_[idx];
|
||||
if (cur == 0)
|
||||
continue;
|
||||
for (unsigned jdx = 0 ; jdx < cur->wires.count() ; jdx += 1)
|
||||
add_wire(cur->wires[jdx]);
|
||||
|
||||
// The port can actually be a list of wires, to
|
||||
// remember to scan the set. Also note the case
|
||||
// where a wire may be connected to multiple
|
||||
// ports, and reuse the link if that happens.
|
||||
for (unsigned jdx = 0; jdx < cur->wires.count(); jdx += 1) {
|
||||
PWire*tmp = add_wire(cur->wires[jdx]);
|
||||
if (tmp != cur->wires[jdx]) {
|
||||
delete cur->wires[jdx];
|
||||
cur->wires[jdx] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,9 +67,14 @@ void Module::add_function(const string &name, PFunction *func)
|
||||
funcs_[name] = func;
|
||||
}
|
||||
|
||||
void Module::add_wire(PWire*wire)
|
||||
PWire* Module::add_wire(PWire*wire)
|
||||
{
|
||||
wires_.push_back(wire);
|
||||
PWire*&ep = wires_[wire->name()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
void Module::add_behavior(PProcess*b)
|
||||
@@ -85,13 +104,22 @@ unsigned Module::find_port(const string&name) const
|
||||
}
|
||||
|
||||
|
||||
PWire* Module::get_wire(const string&name)
|
||||
PWire* Module::get_wire(const string&name) const
|
||||
{
|
||||
for (list<PWire*>::iterator cur = wires_.begin()
|
||||
; cur != wires_.end()
|
||||
map<string,PWire*>::const_iterator obj = wires_.find(name);
|
||||
if (obj == wires_.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
PGate* Module::get_gate(const string&name)
|
||||
{
|
||||
for (list<PGate*>::iterator cur = gates_.begin()
|
||||
; cur != gates_.end()
|
||||
; cur ++ ) {
|
||||
|
||||
if ((*cur)->name() == name)
|
||||
if ((*cur)->get_name() == name)
|
||||
return *cur;
|
||||
}
|
||||
|
||||
@@ -101,6 +129,15 @@ PWire* Module::get_wire(const string&name)
|
||||
|
||||
/*
|
||||
* $Log: Module.cc,v $
|
||||
* Revision 1.10 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.8 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.7 1999/09/17 02:06:25 steve
|
||||
* Handle unconnected module ports.
|
||||
*
|
||||
|
||||
@@ -18,13 +18,14 @@
|
||||
* 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)
|
||||
#ident "$Id: Module.h,v 1.10 1999/11/27 19:07:57 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Module.h,v 1.14 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include "svector.h"
|
||||
# include "named.h"
|
||||
# include <string>
|
||||
class PExpr;
|
||||
class PGate;
|
||||
@@ -76,7 +77,12 @@ class Module {
|
||||
const string&get_name() const { return name_; }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
void add_wire(PWire*wire);
|
||||
|
||||
// The add_wire method adds a wire by name, but only if the
|
||||
// wire name doesn't already exist. Either way, the result is
|
||||
// the existing wire or the pointer passed in.
|
||||
PWire* add_wire(PWire*wire);
|
||||
|
||||
void add_behavior(PProcess*behave);
|
||||
void add_task(const string&name, PTask*def);
|
||||
void add_function(const string&name, PFunction*def);
|
||||
@@ -87,20 +93,23 @@ class Module {
|
||||
|
||||
// Find a wire by name. This is used for connecting gates to
|
||||
// existing wires, etc.
|
||||
PWire* get_wire(const string&name);
|
||||
PWire* get_wire(const string&name) const;
|
||||
PGate* get_gate(const string&name);
|
||||
|
||||
const list<PWire*>& get_wires() const { return wires_; }
|
||||
const map<string,PWire*>& get_wires() const { return wires_; }
|
||||
const list<PGate*>& get_gates() const { return gates_; }
|
||||
const list<PProcess*>& get_behaviors() const { return behaviors_; }
|
||||
|
||||
void dump(ostream&out) const;
|
||||
bool elaborate(Design*, NetScope*scope, svector<PExpr*>*overrides_) const;
|
||||
bool elaborate(Design*, NetScope*scope,
|
||||
named<PExpr*>*parms, unsigned nparms,
|
||||
svector<PExpr*>*overrides_) const;
|
||||
|
||||
private:
|
||||
const string name_;
|
||||
|
||||
svector<port_t*> ports_;
|
||||
list<PWire*> wires_;
|
||||
map<string,PWire*> wires_;
|
||||
list<PGate*> gates_;
|
||||
list<PProcess*> behaviors_;
|
||||
map<string,PTask*> tasks_;
|
||||
@@ -114,6 +123,18 @@ class Module {
|
||||
|
||||
/*
|
||||
* $Log: Module.h,v $
|
||||
* Revision 1.14 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.13 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.12 2000/01/09 05:50:48 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.11 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.10 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PDelays.cc,v 1.1 1999/09/04 19:11:46 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PDelays.cc,v 1.2 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PDelays.h"
|
||||
@@ -96,6 +96,9 @@ void PDelays::eval_delays(Design*des, const string&path,
|
||||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PDelays.h,v 1.1 1999/09/04 19:11:46 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PDelays.h,v 1.2 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
@@ -60,6 +60,9 @@ ostream& operator << (ostream&o, const PDelays&);
|
||||
|
||||
/*
|
||||
* $Log: PDelays.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-1999 Stephen Williams <[email protected]>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PExpr.cc,v 1.11 1999/10/31 04:11:27 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PExpr.cc,v 1.13 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
@@ -43,14 +43,14 @@ NetNet* PExpr::elaborate_net(Design*des, const string&path, unsigned,
|
||||
unsigned long,
|
||||
unsigned long) const
|
||||
{
|
||||
cerr << "Don't know how to elaborate `" << *this
|
||||
<< "' as gates." << endl;
|
||||
cerr << get_line() << ": error: Unable to elaborate `"
|
||||
<< *this << "' as gates." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, const string&path) const
|
||||
{
|
||||
cerr << get_line() << ": expression not valid in assign l-value: "
|
||||
cerr << get_line() << ": error: expression not valid in assign l-value: "
|
||||
<< *this << endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -128,6 +128,12 @@ bool PETernary::is_constant(Module*) const
|
||||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.13 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.12 1999/12/31 17:38:37 steve
|
||||
* Standardize some of the error messages.
|
||||
*
|
||||
* Revision 1.11 1999/10/31 04:11:27 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PExpr_H
|
||||
#define __PExpr_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2000 Stephen Williams <[email protected]>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PExpr.h,v 1.25 1999/11/21 00:13:08 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PExpr.h,v 1.29 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -254,11 +254,26 @@ class PEBinary : public PExpr {
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_bit_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_cmp_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_log_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_mul_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_shift_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
@@ -313,6 +328,18 @@ class PECallFunction : public PExpr {
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.29 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.28 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.27 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.26 1999/12/16 03:46:39 steve
|
||||
* Structural logical or.
|
||||
*
|
||||
* Revision 1.25 1999/11/21 00:13:08 steve
|
||||
* Support memories in continuous assignments.
|
||||
*
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PFunction.cc,v 1.2 1999/08/25 22:22:41 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PFunction.cc,v 1.3 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "PTask.h"
|
||||
@@ -39,6 +39,9 @@ void PFunction::set_output(PWire*o)
|
||||
|
||||
/*
|
||||
* $Log: PFunction.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PGate.cc,v 1.5 1999/09/14 01:50:35 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PGate.cc,v 1.7 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PGate.h"
|
||||
@@ -110,8 +110,50 @@ void PGBuiltin::set_range(PExpr*msb, PExpr*lsb)
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
PGModule::PGModule(const string&type, const string&name, svector<PExpr*>*pins)
|
||||
: PGate(name, pins), type_(type), overrides_(0), pins_(0),
|
||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PGModule::PGModule(const string&type, const string&name,
|
||||
named<PExpr*>*pins, unsigned npins)
|
||||
: PGate(name, 0), type_(type), overrides_(0), pins_(pins),
|
||||
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void PGModule::set_parameters(svector<PExpr*>*o)
|
||||
{
|
||||
assert(overrides_ == 0);
|
||||
overrides_ = o;
|
||||
}
|
||||
|
||||
void PGModule::set_parameters(named<PExpr*>*pa, unsigned npa)
|
||||
{
|
||||
assert(parms_ == 0);
|
||||
assert(overrides_ == 0);
|
||||
parms_ = pa;
|
||||
nparms_ = npa;
|
||||
}
|
||||
|
||||
void PGModule::set_range(PExpr*msb, PExpr*lsb)
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
|
||||
msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PGate.cc,v $
|
||||
* Revision 1.7 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 2000/02/18 05:15:02 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.5 1999/09/14 01:50:35 steve
|
||||
* Handle gates without delays.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGate_H
|
||||
#define __PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,13 +18,16 @@
|
||||
* 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)
|
||||
#ident "$Id: PGate.h,v 1.10 1999/09/04 19:11:46 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PGate.h,v 1.14 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include "named.h"
|
||||
# include "LineInfo.h"
|
||||
# include "PDelays.h"
|
||||
# include <map>
|
||||
# include <string>
|
||||
class PExpr;
|
||||
class PUdp;
|
||||
class Design;
|
||||
@@ -62,6 +65,8 @@ class PGate : public LineInfo {
|
||||
unsigned pin_count() const { return pins_? pins_->count() : 0; }
|
||||
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
|
||||
map<string,string> attributes;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*des, const string&path) const;
|
||||
|
||||
@@ -151,35 +156,58 @@ class PGModule : public PGate {
|
||||
// If the binding of ports is by position, this constructor
|
||||
// builds everything all at once.
|
||||
explicit PGModule(const string&type, const string&name,
|
||||
svector<PExpr*>*overrides, svector<PExpr*>*pins)
|
||||
: PGate(name, pins), type_(type), overrides_(overrides), pins_(0), npins_(0) { }
|
||||
svector<PExpr*>*pins);
|
||||
|
||||
// If the binding of ports is by name, this constructor takes
|
||||
// the bindings and stores them for later elaboration.
|
||||
struct bind_t {
|
||||
string name;
|
||||
PExpr* parm;
|
||||
};
|
||||
explicit PGModule(const string&type, const string&name,
|
||||
svector<PExpr*>*overrides, bind_t*pins, unsigned npins)
|
||||
: PGate(name, 0), type_(type), overrides_(overrides), pins_(pins), npins_(npins) { }
|
||||
named<PExpr*>*pins, unsigned npins);
|
||||
|
||||
|
||||
// Parameter overrides can come as an ordered list, or a set
|
||||
// of named expressions.
|
||||
void set_parameters(svector<PExpr*>*o);
|
||||
void set_parameters(named<PExpr*>*pa, unsigned npa);
|
||||
|
||||
// Modules can be instantiated in ranges. The parser uses this
|
||||
// method to pass the range to the pform.
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*, const string&path) const;
|
||||
|
||||
private:
|
||||
string type_;
|
||||
svector<PExpr*>*overrides_;
|
||||
bind_t*pins_;
|
||||
named<PExpr*>*pins_;
|
||||
unsigned npins_;
|
||||
|
||||
// These members support parameter override by name
|
||||
named<PExpr*>*parms_;
|
||||
unsigned nparms_;
|
||||
|
||||
// Arrays of modules are give if these are set.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
void elaborate_mod_(Design*, Module*mod, const string&path) const;
|
||||
void elaborate_udp_(Design*, PUdp *udp, const string&path) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PGate.h,v $
|
||||
* Revision 1.14 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.13 2000/02/18 05:15:02 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.12 2000/01/09 05:50:48 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.11 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.10 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PTask.cc,v 1.2 1999/07/24 02:11:19 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PTask.cc,v 1.3 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PTask.h"
|
||||
@@ -33,6 +33,9 @@ PTask::~PTask()
|
||||
|
||||
/*
|
||||
* $Log: PTask.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/07/24 02:11:19 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PTask_H
|
||||
#define __PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PTask.h,v 1.6 1999/09/30 21:28:34 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PTask.h,v 1.7 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
@@ -79,6 +79,9 @@ class PFunction : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.7 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/09/30 21:28:34 steve
|
||||
* Handle mutual reference of tasks by elaborating
|
||||
* task definitions in two passes, like functions.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PUdp_H
|
||||
#define __PUdp_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PUdp.h,v 1.3 1999/06/15 03:44:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PUdp.h,v 1.4 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <map>
|
||||
@@ -82,6 +82,9 @@ class PUdp {
|
||||
|
||||
/*
|
||||
* $Log: PUdp.h,v $
|
||||
* Revision 1.4 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PWire.cc,v 1.2 1999/09/10 05:02:09 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PWire.cc,v 1.3 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PWire.h"
|
||||
@@ -100,6 +100,9 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
|
||||
/*
|
||||
* $Log: PWire.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/09/10 05:02:09 steve
|
||||
* Handle integers at task parameters.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PWire_H
|
||||
#define __PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: PWire.h,v 1.6 1999/11/27 19:07:57 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PWire.h,v 1.7 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -82,6 +82,9 @@ class PWire : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PWire.h,v $
|
||||
* Revision 1.7 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
|
||||
+17
-16
@@ -166,6 +166,17 @@ Usage: ivl <options>... file
|
||||
target specific information to the target back-end, or
|
||||
options/parameters to optimization functions, if any are defined.
|
||||
|
||||
-m <module>
|
||||
Cause a named VPI module to be included in the module
|
||||
list. This parameter appends the named module to the end of
|
||||
the VPI_MODULE_LIST. This is an ordered list of modules to be
|
||||
loaded into the simulation at runtime.
|
||||
|
||||
This list can also be set with -fVPI_MODULE_LIST=<list> which
|
||||
sets the list completely. Then, -m after this will append
|
||||
module names to the list sp specified. The default list
|
||||
includes "system".
|
||||
|
||||
-N <file>
|
||||
Dump the elaborated netlist to the named file. The netlist is
|
||||
the folly elaborated netlist, after all the function modules
|
||||
@@ -273,13 +284,6 @@ current state of support for Verilog.
|
||||
|
||||
- Min/Typ/Max expressions: Example: a = (1 : 6 : 14);
|
||||
|
||||
- Memories work, but only in procedural code.
|
||||
|
||||
reg [1:0] b [2:0], bar;
|
||||
wire [1:0] foo;
|
||||
always foo = b[i]; // sorry
|
||||
always @(i) bar = b[i]; // OK
|
||||
|
||||
- `timescale directive
|
||||
|
||||
- force/release/assign/deassign procedural assignments not
|
||||
@@ -295,19 +299,14 @@ current state of support for Verilog.
|
||||
|
||||
- fork/join is not supported in vvm runtime
|
||||
|
||||
- Structural shift operators are in general not supported.
|
||||
Procedural expressions are OK. Constant expressions are OK.
|
||||
|
||||
assign foo = a << b; // sorry
|
||||
always @(a or b) foo = a << b; // OK
|
||||
parameter foo = a << b; // OK
|
||||
|
||||
- Functions in structural contexts are not supported.
|
||||
|
||||
assign foo = user_function(a,b); // sorry
|
||||
always @(a or b) foo = user_function(a,b); // OK
|
||||
|
||||
- multiplicative operators (*, /, %) are not supported.
|
||||
- multiplicative operators (*, /, %) are not supported in
|
||||
general. They do work if the compiler can evaluate them at compile
|
||||
time.
|
||||
|
||||
assign foo = a * b; // sorry
|
||||
always @(a or b) foo = a * b; // sorry
|
||||
@@ -340,15 +339,17 @@ I have received aid in the form of fixes, Verilog guidance, and
|
||||
especially testing from many people, including (in alphabetical order):
|
||||
|
||||
Eric Aardoom <[email protected]>
|
||||
Stephan I. Boettcher <[email protected]>
|
||||
Ed Carter <[email protected]>
|
||||
Larry Doolittle <[email protected]>
|
||||
Guy Hutchison <[email protected]>
|
||||
Ales Hvezda <[email protected]>
|
||||
Yasuhisa Kato <[email protected]>
|
||||
James Lee <[email protected]>
|
||||
Peter Monta <[email protected]>
|
||||
Daniel H. Nelsen <[email protected]>
|
||||
Stefan Petersen <[email protected]>
|
||||
Jason Schonberg <schon@mips.com>
|
||||
Jason Schonberg <schonm@yahoo.com>
|
||||
Stuart Sutherland <[email protected]>
|
||||
Stephen Tell <[email protected]>
|
||||
Stefan Theide <[email protected]>
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: Statement.cc,v 1.16 1999/09/29 18:36:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Statement.cc,v 1.17 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "Statement.h"
|
||||
@@ -163,6 +163,9 @@ PWhile::~PWhile()
|
||||
|
||||
/*
|
||||
* $Log: Statement.cc,v $
|
||||
* Revision 1.17 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.16 1999/09/29 18:36:02 steve
|
||||
* Full case support
|
||||
*
|
||||
|
||||
+6
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef __Statement_H
|
||||
#define __Statement_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: Statement.h,v 1.20 1999/09/29 18:36:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Statement.h,v 1.21 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -347,6 +347,9 @@ class PWhile : public Statement {
|
||||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.21 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.20 1999/09/29 18:36:02 steve
|
||||
* Full case support
|
||||
*
|
||||
|
||||
+6
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef __compiler_H
|
||||
#define __compiler_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: compiler.h,v 1.1 1999/06/06 20:42:48 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: compiler.h,v 1.2 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -35,6 +35,9 @@
|
||||
|
||||
/*
|
||||
* $Log: compiler.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/06/06 20:42:48 steve
|
||||
* Make compiler width a compile time constant.
|
||||
*
|
||||
|
||||
@@ -7,5 +7,47 @@ AC_PROG_CXX
|
||||
AC_CHECK_TOOL(STRIP, strip, true)
|
||||
AC_CHECK_HEADERS(getopt.h)
|
||||
AC_PROG_INSTALL
|
||||
AC_CHECK_LIB(dl,main,[DLLIB=-ldl])
|
||||
AC_SUBST(DLLIB)
|
||||
|
||||
#######################
|
||||
## test for underscores
|
||||
#######################
|
||||
|
||||
AC_MSG_CHECKING("for leading and/or trailing underscores")
|
||||
cat << EOF > underscore.c
|
||||
void underscore(void){}
|
||||
EOF
|
||||
$CC -c underscore.c > /dev/null 2>&1
|
||||
|
||||
CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
|
||||
output=`nm underscore.o|grep underscore_ 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_TRAILING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_TU)
|
||||
fi
|
||||
|
||||
if test "$CC_LEADING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WLU)
|
||||
fi
|
||||
if test "$CC_TRAILING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WTU)
|
||||
fi
|
||||
|
||||
rm underscore.c underscore.o
|
||||
|
||||
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
|
||||
|
||||
#######################
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,13 +16,53 @@
|
||||
* 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)
|
||||
#ident "$Id: cprop.cc,v 1.2 1998/12/02 04:37:13 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: cprop.cc,v 1.7 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "functor.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* This local function returns true if all the the possible drivers of
|
||||
* this link are constant. It will also return true if there are no
|
||||
* drivers at all.
|
||||
*/
|
||||
static bool all_drivers_constant(const NetObj::Link&lnk)
|
||||
{
|
||||
for (const NetObj::Link*cur = lnk.next_link()
|
||||
; *cur != lnk ; cur = cur->next_link()) {
|
||||
|
||||
if (cur->get_dir() == NetObj::Link::INPUT)
|
||||
continue;
|
||||
if (cur->get_dir() == NetObj::Link::PASSIVE)
|
||||
continue;
|
||||
if (! dynamic_cast<const NetConst*>(cur->get_obj()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the value of the constant driving this link,
|
||||
* or Vz if there is no constant. The results of this function are
|
||||
* only meaningful if all_drivers_constant(lnk) == true.
|
||||
*/
|
||||
static verinum::V driven_value(const NetObj::Link&lnk)
|
||||
{
|
||||
for (const NetObj::Link*cur = lnk.next_link()
|
||||
; *cur != lnk ; cur = cur->next_link()) {
|
||||
|
||||
const NetConst*obj;
|
||||
if (obj = dynamic_cast<const NetConst*>(cur->get_obj()))
|
||||
return obj->value(cur->get_pin());
|
||||
}
|
||||
|
||||
return verinum::Vz;
|
||||
}
|
||||
|
||||
/*
|
||||
* The cprop function below invokes constant propogation where
|
||||
* possible. The elaboration generates NetConst objects. I can remove
|
||||
@@ -30,142 +70,249 @@
|
||||
* may even be able to replace nets with a new constant.
|
||||
*/
|
||||
|
||||
static bool is_a_const_node(const NetNode*obj)
|
||||
struct cprop_functor : public functor_t {
|
||||
|
||||
unsigned count;
|
||||
|
||||
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
|
||||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||
};
|
||||
|
||||
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
{
|
||||
return dynamic_cast<const NetConst*>(obj);
|
||||
// For now, only additions are handled.
|
||||
if (obj->attribute("LPM_Direction") != "ADD")
|
||||
return;
|
||||
|
||||
// If the low bit on the A side is 0, then eliminate it from
|
||||
// the adder, and pass the B side directly to the
|
||||
// result. Don't reduce the adder smaller then a 1-bit
|
||||
// adder. These will be eliminated later.
|
||||
while ((obj->width() > 1)
|
||||
&& all_drivers_constant(obj->pin_DataA(0))
|
||||
&& (driven_value(obj->pin_DataA(0)) == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// Now do the same thing on the B side.
|
||||
while ((obj->width() > 1)
|
||||
&& all_drivers_constant(obj->pin_DataB(0))
|
||||
&& (driven_value(obj->pin_DataB(0)) == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataA(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// If the adder is only 1 bit wide, then replace it with the
|
||||
// simple logic gate.
|
||||
if (obj->width() == 1) {
|
||||
NetLogic*tmp;
|
||||
if (obj->pin_Cout().is_linked()) {
|
||||
tmp = new NetLogic(des->local_symbol(obj->name()), 3,
|
||||
NetLogic::AND);
|
||||
connect(tmp->pin(0), obj->pin_Cout());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
des->add_node(tmp);
|
||||
}
|
||||
tmp = new NetLogic(obj->name(), 3, NetLogic::XOR);
|
||||
connect(tmp->pin(0), obj->pin_Result(0));
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool const_into_xnor(Design*des, NetConst*obj,
|
||||
NetLogic*log, unsigned pin)
|
||||
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||
{
|
||||
assert(pin > 0);
|
||||
|
||||
/* if this is the last input pin of the XNOR device, then
|
||||
the device is simply buffering the constant value. */
|
||||
if (log->pin_count() == 2) {
|
||||
cerr << "cprop: delete gate " << log->name() <<
|
||||
" and propogate " << obj->value() << "." << endl;
|
||||
|
||||
assert(pin == 1);
|
||||
connect(log->pin(0), log->pin(1));
|
||||
|
||||
delete log;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If this is a constant 0, then replace the gate with one
|
||||
1-pin smaller. Skip this pin. */
|
||||
if (obj->value() == verinum::V0) {
|
||||
cerr << "cprop: disconnect pin " << pin << " from gate "
|
||||
<< log->name() << "." << endl;
|
||||
|
||||
NetLogic*tmp = new NetLogic(log->name(),
|
||||
log->pin_count()-1,
|
||||
NetLogic::XNOR);
|
||||
connect(log->pin(0), tmp->pin(0));
|
||||
unsigned idx, jdx;
|
||||
for (idx = 1, jdx = 1 ; idx < log->pin_count() ; idx += 1) {
|
||||
if (idx == pin) continue;
|
||||
connect(log->pin(idx), tmp->pin(jdx));
|
||||
jdx += 1;
|
||||
// Look for and count unlinked FF outputs. Note that if the
|
||||
// Data and Q pins are connected together, they can be removed
|
||||
// from the circuit.
|
||||
unsigned unlinked_count = 0;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (connected(obj->pin_Data(idx), obj->pin_Q(idx))) {
|
||||
obj->pin_Data(idx).unlink();
|
||||
obj->pin_Q(idx).unlink();
|
||||
}
|
||||
|
||||
delete log;
|
||||
des->add_node(tmp);
|
||||
return true;
|
||||
if (! obj->pin_Q(idx).is_linked())
|
||||
unlinked_count += 1;
|
||||
}
|
||||
|
||||
/* If this is a constant 1, then replace the gate with an XOR
|
||||
that is 1-pin smaller. Removing the constant 1 causes the
|
||||
sense of the output to change. */
|
||||
if (obj->value() == verinum::V1) {
|
||||
cerr << "cprop: disconnect pin " << pin << " from gate "
|
||||
<< log->name() << "." << endl;
|
||||
|
||||
NetLogic*tmp = new NetLogic(log->name(),
|
||||
log->pin_count()-1,
|
||||
NetLogic::XOR);
|
||||
connect(log->pin(0), tmp->pin(0));
|
||||
unsigned idx, jdx;
|
||||
for (idx = 1, jdx = 1 ; idx < log->pin_count() ; idx += 1) {
|
||||
if (idx == pin) continue;
|
||||
connect(log->pin(idx), tmp->pin(jdx));
|
||||
jdx += 1;
|
||||
}
|
||||
|
||||
delete log;
|
||||
des->add_node(tmp);
|
||||
return true;
|
||||
// If the entire FF is unlinked, remove the whole thing.
|
||||
if (unlinked_count == obj->width()) {
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this is a constant X or Z, then the gate is certain to
|
||||
generate an X. Replace the gate with a constant X. This may
|
||||
cause other signals all over to become dangling. */
|
||||
if ((obj->value() == verinum::Vx) || (obj->value() == verinum::Vz)) {
|
||||
cerr << "cprop: replace gate " << log->name() << " with "
|
||||
"a constant X." << endl;
|
||||
// If some of the FFs are unconnected, make a new FF array
|
||||
// that does not include the useless FF devices.
|
||||
if (unlinked_count > 0) {
|
||||
NetFF*tmp = new NetFF(obj->name(), obj->width()-unlinked_count);
|
||||
connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
connect(tmp->pin_Enable(), obj->pin_Enable());
|
||||
connect(tmp->pin_Aload(), obj->pin_Aload());
|
||||
connect(tmp->pin_Aset(), obj->pin_Aset());
|
||||
connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
connect(tmp->pin_Sload(), obj->pin_Sload());
|
||||
connect(tmp->pin_Sset(), obj->pin_Sset());
|
||||
connect(tmp->pin_Sclr(), obj->pin_Sclr());
|
||||
|
||||
NetConst*tmp = new NetConst(log->name(), verinum::Vx);
|
||||
connect(log->pin(0), tmp->pin(0));
|
||||
delete log;
|
||||
unsigned tidx = 0;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
if (obj->pin_Q(idx).is_linked()) {
|
||||
connect(tmp->pin_Data(tidx), obj->pin_Data(idx));
|
||||
connect(tmp->pin_Q(tidx), obj->pin_Q(idx));
|
||||
tidx += 1;
|
||||
}
|
||||
|
||||
assert(tidx == obj->width() - unlinked_count);
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
return true;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void look_for_core_logic(Design*des, NetConst*obj)
|
||||
void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
{
|
||||
NetObj*cur = obj;
|
||||
unsigned pin = 0;
|
||||
for (obj->pin(0).next_link(cur, pin)
|
||||
; cur != obj
|
||||
; cur->pin(pin).next_link(cur, pin)) {
|
||||
switch (obj->type()) {
|
||||
|
||||
NetLogic*log = dynamic_cast<NetLogic*>(cur);
|
||||
if (log == 0)
|
||||
continue;
|
||||
|
||||
bool flag = false;
|
||||
switch (log->type()) {
|
||||
case NetLogic::XNOR:
|
||||
flag = const_into_xnor(des, obj, log, pin);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case NetLogic::AND:
|
||||
// If there is one zero input to an AND gate, we know
|
||||
// the resulting output is going to be zero and can
|
||||
// elininate the gate.
|
||||
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
|
||||
if (! all_drivers_constant(obj->pin(idx)))
|
||||
continue;
|
||||
if (driven_value(obj->pin(idx)) == verinum::V0) {
|
||||
connect(obj->pin(0), obj->pin(idx));
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the optimization test tells me that a link was
|
||||
deleted, restart the scan. */
|
||||
if (flag) obj->pin(0).next_link(cur, pin);
|
||||
// There are no zero constant drivers. If there are any
|
||||
// non-constant drivers, give up.
|
||||
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
|
||||
if (! all_drivers_constant(obj->pin(idx)))
|
||||
return;
|
||||
}
|
||||
|
||||
// If there are any non-1 values (Vx or Vz) then the
|
||||
// result is Vx.
|
||||
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
|
||||
if (driven_value(obj->pin(idx)) != verinum::V1) {
|
||||
connect(obj->pin(0), obj->pin(idx));
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// What's left? The inputs are all 1's, return the first
|
||||
// input as the output value and remove the gate.
|
||||
connect(obj->pin(0), obj->pin(1));
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function looks to see if the constant is connected to nothing
|
||||
* This functor looks to see if the constant is connected to nothing
|
||||
* but signals. If that is the case, delete the dangling constant and
|
||||
* the now useless signals.
|
||||
* the now useless signals. This functor is applied after the regular
|
||||
* functor to clean up dangling constants that might be left behind.
|
||||
*/
|
||||
static void dangling_const(Design*des, NetConst*obj)
|
||||
struct cprop_dc_functor : public functor_t {
|
||||
|
||||
virtual void lpm_const(Design*des, NetConst*obj);
|
||||
};
|
||||
|
||||
void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
{
|
||||
// If there are any links that take input, abort this
|
||||
// operation.
|
||||
if (count_inputs(obj->pin(0)) > 0)
|
||||
return;
|
||||
// If there are any links that take input, the constant is
|
||||
// used structurally somewhere.
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1)
|
||||
if (count_inputs(obj->pin(idx)) > 0)
|
||||
return;
|
||||
|
||||
// Look for signals that have NetESignal nodes attached to
|
||||
// them. If I find any, this this constant is used by a
|
||||
// behavioral expression somewhere.
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
|
||||
NetObj*cur;
|
||||
unsigned pin;
|
||||
obj->pin(idx).next_link(cur, pin);
|
||||
while (cur != obj) {
|
||||
NetNet*tmp = dynamic_cast<NetNet*>(cur);
|
||||
if (tmp && tmp->get_eref() > 0)
|
||||
return;
|
||||
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no other drivers, delete all the signals that
|
||||
// are also dangling.
|
||||
if (count_outputs(obj->pin(0)) == 1) {
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
|
||||
if (count_outputs(obj->pin(idx)) != 1)
|
||||
continue;
|
||||
|
||||
NetObj*cur;
|
||||
unsigned pin;
|
||||
obj->pin(0).next_link(cur, pin);
|
||||
obj->pin(idx).next_link(cur, pin);
|
||||
while (cur != obj) {
|
||||
cerr << "cprop: delete dangling signal " << cur->name() <<
|
||||
"." << endl;
|
||||
delete cur;
|
||||
obj->pin(0).next_link(cur, pin);
|
||||
NetNet*tmp = dynamic_cast<NetNet*>(cur);
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
assert(tmp->get_eref() == 0);
|
||||
cerr << "cprop: delete dangling signal " <<
|
||||
tmp->name() << "." << endl;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,20 +320,38 @@ static void dangling_const(Design*des, NetConst*obj)
|
||||
delete obj;
|
||||
}
|
||||
|
||||
|
||||
void cprop(Design*des)
|
||||
{
|
||||
des->clear_node_marks();
|
||||
while (NetNode*obj = des->find_node(&is_a_const_node)) {
|
||||
NetConst*cur = dynamic_cast<NetConst*>(obj);
|
||||
look_for_core_logic(des, cur);
|
||||
cur->set_mark();
|
||||
dangling_const(des, cur);
|
||||
}
|
||||
// Continually propogate constants until a scan finds nothing
|
||||
// to do.
|
||||
cprop_functor prop;
|
||||
do {
|
||||
prop.count = 0;
|
||||
des->functor(&prop);
|
||||
} while (prop.count > 0);
|
||||
|
||||
cprop_dc_functor dc;
|
||||
des->functor(&dc);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.7 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 2000/01/02 17:56:42 steve
|
||||
* Do not delete constants that input to exressions.
|
||||
*
|
||||
* Revision 1.5 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.4 1999/12/17 06:18:15 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.3 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.2 1998/12/02 04:37:13 steve
|
||||
* Add the nobufz function to eliminate bufz objects,
|
||||
* Object links are marked with direction,
|
||||
|
||||
+37
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: design_dump.cc,v 1.61 1999/11/28 23:42:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: design_dump.cc,v 1.67 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -142,8 +142,14 @@ void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetCompare::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_COMPARE (NetCompare): " <<
|
||||
name() << endl;
|
||||
o << setw(ind) << "" << "LPM_COMPARE (NetCompare): " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetMult::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -189,7 +195,10 @@ void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant " << value_ << ": " << name() << endl;
|
||||
o << setw(ind) << "" << "constant ";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
o << value_[idx-1];
|
||||
o << ": " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
@@ -428,9 +437,7 @@ void NetAssignMem::dump(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "";
|
||||
o << "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "";
|
||||
o << memory()->name() << "[";
|
||||
index()->dump(o);
|
||||
o << "] = ";
|
||||
o << memory()->name() << "[" << index()->name() << "] = ";
|
||||
rval()->dump(o);
|
||||
o << ";" << endl;
|
||||
}
|
||||
@@ -440,9 +447,7 @@ void NetAssignMemNB::dump(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "";
|
||||
o << "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "";
|
||||
o << memory()->name() << "[";
|
||||
index()->dump(o);
|
||||
o << "] <= ";
|
||||
o << memory()->name() << "[" << index()->name() << "] <= ";
|
||||
rval()->dump(o);
|
||||
o << ";" << endl;
|
||||
}
|
||||
@@ -583,7 +588,7 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetScope::dump(ostream&o) const
|
||||
{
|
||||
o << name_;
|
||||
o << name();
|
||||
switch (type_) {
|
||||
case BEGIN_END:
|
||||
o << " sequential block";
|
||||
@@ -745,7 +750,7 @@ void NetESubSignal::dump(ostream&o) const
|
||||
void NetEMemory::dump(ostream&o) const
|
||||
{
|
||||
o << mem_->name() << "[";
|
||||
idx_->dump(o);
|
||||
if (idx_) idx_->dump(o);
|
||||
o << "]";
|
||||
}
|
||||
|
||||
@@ -866,6 +871,24 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.67 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.66 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.65 2000/01/10 01:35:23 steve
|
||||
* Elaborate parameters afer binding of overrides.
|
||||
*
|
||||
* Revision 1.64 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.63 1999/12/12 06:03:14 steve
|
||||
* Allow memories without indices in expressions.
|
||||
*
|
||||
* Revision 1.62 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.61 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: dup_expr.cc,v 1.1 1999/11/27 19:07:57 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: dup_expr.cc,v 1.2 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -31,6 +31,9 @@ NetEScope* NetEScope::dup_expr() const
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
|
||||
+61
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: elab_expr.cc,v 1.12 1999/11/30 04:54:01 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_expr.cc,v 1.16 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -68,6 +68,11 @@ NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '*':
|
||||
tmp = new NetEBMult(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case 'r':
|
||||
tmp = new NetEBShift(op_, lp, rp);
|
||||
@@ -159,6 +164,42 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, const string&path) const
|
||||
}
|
||||
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
unsigned repeat = 1;
|
||||
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
if (repeat_) {
|
||||
verinum*vrep = repeat_->eval_const(des, path);
|
||||
if (vrep == 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = vrep->as_ulong();
|
||||
delete vrep;
|
||||
}
|
||||
|
||||
/* Make the empty concat expression. */
|
||||
NetEConcat*tmp = new NetEConcat(parms_.count(), repeat);
|
||||
tmp->set_line(*this);
|
||||
|
||||
/* Elaborate all the parameters and attach them to the concat node. */
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
assert(parms_[idx]);
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, path);
|
||||
if (ex == 0) continue;
|
||||
ex->set_line(*parms_[idx]);
|
||||
tmp->set(idx, ex);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
// System identifiers show up in the netlist as identifiers.
|
||||
@@ -263,10 +304,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
// object to handle it.
|
||||
if (NetMemory*mem = des->find_memory(path, text_)) {
|
||||
if (msb_ == 0) {
|
||||
NetEMemory*node = new NetEMemory(mem);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
#if 0
|
||||
cerr << get_line() << ": error: Memory ``" << name <<
|
||||
"'' referenced without an index expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
assert(msb_ != 0);
|
||||
assert(lsb_ == 0);
|
||||
@@ -332,6 +378,18 @@ NetExpr*PETernary::elaborate_expr(Design*des, const string&path) const
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.16 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.15 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.14 2000/01/01 06:18:00 steve
|
||||
* Handle synthesis of concatenation.
|
||||
*
|
||||
* Revision 1.13 1999/12/12 06:03:14 steve
|
||||
* Allow memories without indices in expressions.
|
||||
*
|
||||
* Revision 1.12 1999/11/30 04:54:01 steve
|
||||
* Match scope names as last resort.
|
||||
*
|
||||
|
||||
+631
-152
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,12 +16,13 @@
|
||||
* 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)
|
||||
#ident "$Id: elab_net.cc,v 1.11 1999/12/02 04:08:10 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_net.cc,v 1.23 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
/*
|
||||
* Elaborating binary operations generally involves elaborating the
|
||||
@@ -35,9 +36,18 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path,
|
||||
unsigned long decay) const
|
||||
{
|
||||
switch (op_) {
|
||||
case '*':
|
||||
//case '/':
|
||||
//case '%':
|
||||
return elaborate_net_mul_(des, path, width, rise, fall, decay);
|
||||
case '+':
|
||||
case '-':
|
||||
return elaborate_net_add_(des, path, width, rise, fall, decay);
|
||||
case '|': // Bitwise OR
|
||||
case '&':
|
||||
case '^':
|
||||
case 'X': // Exclusing NOR
|
||||
return elaborate_net_bit_(des, path, width, rise, fall, decay);
|
||||
case 'E':
|
||||
case 'e':
|
||||
case 'n':
|
||||
@@ -46,6 +56,9 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path,
|
||||
case 'L': // <=
|
||||
case 'G': // >=
|
||||
return elaborate_net_cmp_(des, path, width, rise, fall, decay);
|
||||
case 'a': // && (logical and)
|
||||
case 'o': // || (logical or)
|
||||
return elaborate_net_log_(des, path, width, rise, fall, decay);
|
||||
case 'l': // <<
|
||||
case 'r': // >>
|
||||
return elaborate_net_shift_(des, path, width, rise, fall, decay);
|
||||
@@ -72,98 +85,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path,
|
||||
|
||||
switch (op_) {
|
||||
case '^': // XOR
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE,
|
||||
lsig->pin_count());
|
||||
osig->local_flag(true);
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
gate = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::XOR);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
des->add_signal(osig);
|
||||
break;
|
||||
|
||||
case 'X': // XNOR
|
||||
case '&': // AND
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE,
|
||||
lsig->pin_count());
|
||||
osig->local_flag(true);
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
gate = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::AND);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
des->add_signal(osig);
|
||||
break;
|
||||
|
||||
case '|': // Bitwise OR
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE,
|
||||
lsig->pin_count());
|
||||
osig->local_flag(true);
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
gate = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::OR);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
des->add_signal(osig);
|
||||
break;
|
||||
|
||||
case 'a': // && (logical AND)
|
||||
gate = new NetLogic(des->local_symbol(path), 3, NetLogic::AND);
|
||||
|
||||
// The first OR gate returns 1 if the left value is true...
|
||||
if (lsig->pin_count() > 1) {
|
||||
gate_t = new NetLogic(des->local_symbol(path),
|
||||
1+lsig->pin_count(), NetLogic::OR);
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(gate_t->pin(idx+1), lsig->pin(idx));
|
||||
connect(gate->pin(1), gate_t->pin(0));
|
||||
des->add_node(gate_t);
|
||||
} else {
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
}
|
||||
|
||||
// The second OR gate returns 1 if the right value is true...
|
||||
if (rsig->pin_count() > 1) {
|
||||
gate_t = new NetLogic(des->local_symbol(path),
|
||||
1+rsig->pin_count(), NetLogic::OR);
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(gate_t->pin(idx+1), rsig->pin(idx));
|
||||
connect(gate->pin(2), gate_t->pin(0));
|
||||
des->add_node(gate_t);
|
||||
} else {
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
}
|
||||
|
||||
// The output is the AND of the two logic values.
|
||||
osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
osig->local_flag(true);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
des->add_signal(osig);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
case 'E': // === (Case equals)
|
||||
@@ -236,8 +161,14 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path,
|
||||
if (rsig->pin_count() > lsig->pin_count())
|
||||
width = rsig->pin_count();
|
||||
|
||||
// If the desired output size if creater then the largest
|
||||
// operand, then include the carry of the adder as an output.
|
||||
unsigned owidth = width;
|
||||
if (lwidth > owidth)
|
||||
owidth = width + 1;
|
||||
|
||||
// Make the adder as wide as the widest operand
|
||||
osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE, width);
|
||||
osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE, owidth);
|
||||
NetAddSub*adder = new NetAddSub(name, width);
|
||||
|
||||
// Connect the adder to the various parts.
|
||||
@@ -245,8 +176,10 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path,
|
||||
connect(lsig->pin(idx), adder->pin_DataA(idx));
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(rsig->pin(idx), adder->pin_DataB(idx));
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(osig->pin(idx), adder->pin_Result(idx));
|
||||
if (owidth > width)
|
||||
connect(osig->pin(width), adder->pin_Cout());
|
||||
|
||||
gate = adder;
|
||||
des->add_signal(osig);
|
||||
@@ -273,7 +206,127 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path,
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the various binary comparison operators.
|
||||
* Elaborate various bitwise logic operators. These are all similar in
|
||||
* that they take operants of equal width, and each bit does not
|
||||
* affect any other bits. Also common about all this is how bit widths
|
||||
* of the operands are handled, when they do not match.
|
||||
*/
|
||||
NetNet* PEBinary::elaborate_net_bit_(Design*des, const string&path,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const
|
||||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, path, width, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, path, width, 0, 0, 0);
|
||||
if (lsig == 0) {
|
||||
cerr << get_line() << ": error: Cannot elaborate ";
|
||||
left_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
if (rsig == 0) {
|
||||
cerr << get_line() << ": error: Cannot elaborate ";
|
||||
right_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lsig->pin_count() < rsig->pin_count())
|
||||
lsig = pad_to_width(des, path, lsig, rsig->pin_count());
|
||||
if (rsig->pin_count() < lsig->pin_count())
|
||||
rsig = pad_to_width(des, path, rsig, lsig->pin_count());
|
||||
|
||||
if (lsig->pin_count() != rsig->pin_count()) {
|
||||
cerr << get_line() << ": internal error: lsig pin count ("
|
||||
<< lsig->pin_count() << ") != rsig pin count ("
|
||||
<< rsig->pin_count() << ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
|
||||
NetNet*osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE,
|
||||
lsig->pin_count());
|
||||
osig->local_flag(true);
|
||||
|
||||
switch (op_) {
|
||||
case '^': // XOR
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::XOR);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'X': // XNOR
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::XNOR);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
break;
|
||||
|
||||
case '&': // AND
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::AND);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
break;
|
||||
|
||||
case '|': // Bitwise OR
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(des->local_symbol(path),
|
||||
3, NetLogic::OR);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
des->add_signal(osig);
|
||||
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(lsig))
|
||||
delete tmp;
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(rsig))
|
||||
delete tmp;
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the various binary comparison operators. The comparison
|
||||
* operators return a single bit result, no matter what, so the left
|
||||
* and right values can have their own size. The only restriction is
|
||||
* that they have the same size.
|
||||
*/
|
||||
NetNet* PEBinary::elaborate_net_cmp_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
@@ -296,33 +349,40 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, const string&path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned dwidth = lsig->pin_count();
|
||||
if (rsig->pin_count() > dwidth) dwidth = rsig->pin_count();
|
||||
|
||||
NetNet*zero = 0;
|
||||
if (lsig->pin_count() != rsig->pin_count()) {
|
||||
cerr << get_line() << ": internal error: Cannot match "
|
||||
"structural net widths " << lsig->pin_count() <<
|
||||
" and " << rsig->pin_count() << "." << endl;
|
||||
delete lsig;
|
||||
delete rsig;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
NetConst*tmp = new NetConst(des->local_symbol(path), verinum::V0);
|
||||
des->add_node(tmp);
|
||||
zero = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
des->add_signal(zero);
|
||||
connect(tmp->pin(0), zero->pin(0));
|
||||
}
|
||||
|
||||
NetNet*osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
osig->local_flag(true);
|
||||
|
||||
NetNode*gate;
|
||||
NetNode*gate_t;
|
||||
//NetNode*gate_t;
|
||||
|
||||
switch (op_) {
|
||||
case '<':
|
||||
case '>':
|
||||
case 'L':
|
||||
case 'G': {
|
||||
NetCompare*cmp = new NetCompare(des->local_symbol(path),
|
||||
lsig->pin_count());
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetCompare*cmp = new
|
||||
NetCompare(des->local_symbol(path), dwidth);
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(cmp->pin_DataA(idx), lsig->pin(idx));
|
||||
for (unsigned idx = lsig->pin_count(); idx < dwidth ; idx += 1)
|
||||
connect(cmp->pin_DataA(idx), zero->pin(0));
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(cmp->pin_DataB(idx), rsig->pin(idx));
|
||||
}
|
||||
for (unsigned idx = rsig->pin_count(); idx < dwidth ; idx += 1)
|
||||
connect(cmp->pin_DataB(idx), zero->pin(0));
|
||||
|
||||
switch (op_) {
|
||||
case '<':
|
||||
connect(cmp->pin_ALB(), osig->pin(0));
|
||||
@@ -348,18 +408,27 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, const string&path,
|
||||
1+lsig->pin_count(),
|
||||
NetLogic::AND);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
gate_t = new NetCaseCmp(des->local_symbol(path));
|
||||
connect(gate_t->pin(1), lsig->pin(idx));
|
||||
connect(gate_t->pin(2), rsig->pin(idx));
|
||||
connect(gate_t->pin(0), gate->pin(idx+1));
|
||||
des->add_node(gate_t);
|
||||
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
|
||||
NetCaseCmp*cmp = new NetCaseCmp(des->local_symbol(path));
|
||||
|
||||
if (idx < lsig->pin_count())
|
||||
connect(cmp->pin(1), lsig->pin(idx));
|
||||
else
|
||||
connect(cmp->pin(1), zero->pin(0));
|
||||
|
||||
if (idx < rsig->pin_count())
|
||||
connect(cmp->pin(2), rsig->pin(idx));
|
||||
else
|
||||
connect(cmp->pin(2), zero->pin(0));
|
||||
|
||||
connect(cmp->pin(0), gate->pin(idx+1));
|
||||
des->add_node(cmp);
|
||||
|
||||
// Attach a label to this intermediate wire
|
||||
NetNet*tmp = new NetNet(0, des->local_symbol(path),
|
||||
NetNet::WIRE);
|
||||
tmp->local_flag(true);
|
||||
connect(gate_t->pin(0), tmp->pin(0));
|
||||
connect(cmp->pin(0), tmp->pin(0));
|
||||
des->add_signal(tmp);
|
||||
}
|
||||
break;
|
||||
@@ -367,31 +436,57 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, const string&path,
|
||||
|
||||
case 'e': // ==
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+lsig->pin_count(),
|
||||
NetLogic::AND);
|
||||
1+dwidth,NetLogic::AND);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
gate_t = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::XNOR);
|
||||
connect(gate_t->pin(1), lsig->pin(idx));
|
||||
connect(gate_t->pin(2), rsig->pin(idx));
|
||||
connect(gate_t->pin(0), gate->pin(idx+1));
|
||||
des->add_node(gate_t);
|
||||
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
|
||||
NetLogic*cmp = new NetLogic(des->local_symbol(path),
|
||||
3, NetLogic::XNOR);
|
||||
if (idx < lsig->pin_count())
|
||||
connect(cmp->pin(1), lsig->pin(idx));
|
||||
else
|
||||
connect(cmp->pin(1), zero->pin(0));
|
||||
|
||||
if (idx < rsig->pin_count())
|
||||
connect(cmp->pin(2), rsig->pin(idx));
|
||||
else
|
||||
connect(cmp->pin(2), zero->pin(0));
|
||||
|
||||
connect(cmp->pin(0), gate->pin(idx+1));
|
||||
des->add_node(cmp);
|
||||
|
||||
NetNet*tmp = new NetNet(0, des->local_symbol(path),
|
||||
NetNet::WIRE);
|
||||
tmp->local_flag(true);
|
||||
connect(cmp->pin(0), tmp->pin(0));
|
||||
des->add_signal(tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n': // !=
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+lsig->pin_count(),
|
||||
NetLogic::OR);
|
||||
1+dwidth, NetLogic::OR);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
gate_t = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::XOR);
|
||||
connect(gate_t->pin(1), lsig->pin(idx));
|
||||
connect(gate_t->pin(2), rsig->pin(idx));
|
||||
connect(gate_t->pin(0), gate->pin(idx+1));
|
||||
des->add_node(gate_t);
|
||||
NetLogic*cmp = new NetLogic(des->local_symbol(path), 3,
|
||||
NetLogic::XOR);
|
||||
if (idx < lsig->pin_count())
|
||||
connect(cmp->pin(1), lsig->pin(idx));
|
||||
else
|
||||
connect(cmp->pin(1), zero->pin(0));
|
||||
|
||||
if (idx < rsig->pin_count())
|
||||
connect(cmp->pin(2), rsig->pin(idx));
|
||||
else
|
||||
connect(cmp->pin(2), zero->pin(0));
|
||||
|
||||
connect(cmp->pin(0), gate->pin(idx+1));
|
||||
des->add_node(cmp);
|
||||
|
||||
NetNet*tmp = new NetNet(0, des->local_symbol(path),
|
||||
NetNet::WIRE);
|
||||
tmp->local_flag(true);
|
||||
connect(cmp->pin(0), tmp->pin(0));
|
||||
des->add_signal(tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -408,6 +503,122 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, const string&path,
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PEBinary::elaborate_net_log_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const
|
||||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, path, 0, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, path, 0, 0, 0, 0);
|
||||
if (lsig == 0) {
|
||||
cerr << get_line() << ": error: Cannot elaborate ";
|
||||
left_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
if (rsig == 0) {
|
||||
cerr << get_line() << ": error: Cannot elaborate ";
|
||||
right_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetLogic*gate;
|
||||
NetLogic*gate_t;
|
||||
switch (op_) {
|
||||
case 'a':
|
||||
gate = new NetLogic(des->local_symbol(path), 3, NetLogic::AND);
|
||||
break;
|
||||
case 'o':
|
||||
gate = new NetLogic(des->local_symbol(path), 3, NetLogic::OR);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
|
||||
// The first OR gate returns 1 if the left value is true...
|
||||
if (lsig->pin_count() > 1) {
|
||||
gate_t = new NetLogic(des->local_symbol(path),
|
||||
1+lsig->pin_count(), NetLogic::OR);
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(gate_t->pin(idx+1), lsig->pin(idx));
|
||||
connect(gate->pin(1), gate_t->pin(0));
|
||||
des->add_node(gate_t);
|
||||
} else {
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
}
|
||||
|
||||
// The second OR gate returns 1 if the right value is true...
|
||||
if (rsig->pin_count() > 1) {
|
||||
gate_t = new NetLogic(des->local_symbol(path),
|
||||
1+rsig->pin_count(), NetLogic::OR);
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(gate_t->pin(idx+1), rsig->pin(idx));
|
||||
connect(gate->pin(2), gate_t->pin(0));
|
||||
des->add_node(gate_t);
|
||||
} else {
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
}
|
||||
|
||||
// The output is the AND/OR of the two logic values.
|
||||
NetNet*osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
osig->local_flag(true);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
des->add_signal(osig);
|
||||
des->add_node(gate);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PEBinary::elaborate_net_mul_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const
|
||||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, path, 0, 0, 0, 0);
|
||||
if (lsig == 0) return 0;
|
||||
NetNet*rsig = right_->elaborate_net(des, path, 0, 0, 0, 0);
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
unsigned rwidth = lsig->pin_count() + rsig->pin_count();
|
||||
NetMult*mult = new NetMult(des->local_symbol(path), rwidth,
|
||||
lsig->pin_count(),
|
||||
rsig->pin_count());
|
||||
des->add_node(mult);
|
||||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(mult->pin_DataA(idx), lsig->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(mult->pin_DataB(idx), rsig->pin(idx));
|
||||
|
||||
if (lwidth == 0) lwidth = rwidth;
|
||||
NetNet*osig = new NetNet(0, des->local_symbol(path),
|
||||
NetNet::IMPLICIT, lwidth);
|
||||
osig->local_flag(true);
|
||||
des->add_signal(osig);
|
||||
|
||||
unsigned cnt = osig->pin_count();
|
||||
if (cnt > rwidth) cnt = rwidth;
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
connect(mult->pin_Result(idx), osig->pin(idx));
|
||||
|
||||
/* If the lvalue is larger then the result, then pad the
|
||||
output with constant 0. */
|
||||
if (cnt < osig->pin_count()) {
|
||||
NetConst*tmp = new NetConst(des->local_symbol(path), verinum::V0);
|
||||
des->add_node(tmp);
|
||||
for (unsigned idx = cnt ; idx < osig->pin_count() ; idx += 1)
|
||||
connect(osig->pin(idx), tmp->pin(0));
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PEBinary::elaborate_net_shift_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
@@ -417,6 +628,9 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, const string&path,
|
||||
NetNet*lsig = left_->elaborate_net(des, path, lwidth, 0, 0, 0);
|
||||
if (lsig == 0) return 0;
|
||||
|
||||
if (lsig->pin_count() > lwidth)
|
||||
lwidth = lsig->pin_count();
|
||||
|
||||
/* Handle the special case of a constant shift amount. There
|
||||
is no reason in this case to create a gate at all, just
|
||||
connect the lsig to the osig with the bit positions
|
||||
@@ -458,26 +672,44 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, const string&path,
|
||||
return osig;
|
||||
}
|
||||
|
||||
// Calculate the number of useful bits for the shift amount,
|
||||
// and elaborate the right_ expression as the shift amount.
|
||||
unsigned dwid = 0;
|
||||
while ((1 << dwid) < lsig->pin_count())
|
||||
while ((1 << dwid) < lwidth)
|
||||
dwid += 1;
|
||||
|
||||
NetNet*rsig = right_->elaborate_net(des, path, dwid, 0, 0, 0);
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
// Make the shift device itself, and the output
|
||||
// NetNet. Connect the Result output pins to the osig signal
|
||||
NetCLShift*gate = new NetCLShift(des->local_symbol(path),
|
||||
lsig->pin_count(),
|
||||
rsig->pin_count());
|
||||
lwidth, rsig->pin_count());
|
||||
|
||||
NetNet*osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE,
|
||||
lsig->pin_count());
|
||||
NetNet*osig = new NetNet(0, des->local_symbol(path),
|
||||
NetNet::WIRE, lwidth);
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
|
||||
connect(osig->pin(idx), gate->pin_Result(idx));
|
||||
|
||||
// Connect the lsig (the left expression) to the Data input,
|
||||
// and pad it if necessary with constant zeros.
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(lsig->pin(idx), gate->pin_Data(idx));
|
||||
|
||||
if (lsig->pin_count() < lwidth) {
|
||||
NetConst*zero = new NetConst(des->local_symbol(path), verinum::V0);
|
||||
NetTmp*tmp = new NetTmp(des->local_symbol(path));
|
||||
des->add_node(zero);
|
||||
des->add_signal(tmp);
|
||||
connect(zero->pin(0), tmp->pin(0));
|
||||
for (unsigned idx = lsig->pin_count() ; idx < lwidth ; idx += 1)
|
||||
connect(zero->pin(0), gate->pin_Data(idx));
|
||||
}
|
||||
|
||||
// Connect the rsig (the shift amount expression) to the
|
||||
// Distance input.
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(rsig->pin(idx), gate->pin_Distance(idx));
|
||||
|
||||
@@ -598,12 +830,11 @@ NetNet* PEIdent::elaborate_net(Design*des, const string&path,
|
||||
verinum pvalue = pc->value();
|
||||
sig = new NetNet(0, path+"."+text_, NetNet::IMPLICIT,
|
||||
pc->expr_width());
|
||||
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) {
|
||||
NetConst*cp = new NetConst(des->local_symbol(path),
|
||||
pvalue[idx]);
|
||||
connect(sig->pin(idx), cp->pin(0));
|
||||
des->add_node(cp);
|
||||
}
|
||||
NetConst*cp = new NetConst(des->local_symbol(path), pvalue);
|
||||
des->add_node(cp);
|
||||
des->add_signal(sig);
|
||||
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1)
|
||||
connect(sig->pin(idx), cp->pin(idx));
|
||||
|
||||
} else {
|
||||
|
||||
@@ -836,20 +1067,77 @@ NetNet* PENumber::elaborate_net(Design*des, const string&path,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const
|
||||
{
|
||||
/* If we are constrained by a l-value size, then just make a
|
||||
number constant with the correct size and set as many bits
|
||||
in that constant as make sense. Pad excess with zeros. */
|
||||
if (lwidth > 0) {
|
||||
NetNet*net = new NetNet(0, des->local_symbol(path),
|
||||
NetNet::IMPLICIT, lwidth);
|
||||
net->local_flag(true);
|
||||
|
||||
verinum num(verinum::V0, net->pin_count());
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < num.len() && idx < value_->len(); idx += 1)
|
||||
num.set(idx, value_->get(idx));
|
||||
|
||||
NetConst*tmp = new NetConst(des->local_symbol(path), num);
|
||||
for (idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
connect(net->pin(idx), tmp->pin(idx));
|
||||
|
||||
des->add_node(tmp);
|
||||
des->add_signal(net);
|
||||
return net;
|
||||
}
|
||||
|
||||
/* If the number has a length, then use that to size the
|
||||
number. Generate a constant object of exactly the user
|
||||
specified size. */
|
||||
if (value_->has_len()) {
|
||||
NetNet*net = new NetNet(0, des->local_symbol(path),
|
||||
NetNet::IMPLICIT, value_->len());
|
||||
net->local_flag(true);
|
||||
NetConst*tmp = new NetConst(des->local_symbol(path), *value_);
|
||||
for (unsigned idx = 0 ; idx < value_->len() ; idx += 1)
|
||||
connect(net->pin(idx), tmp->pin(idx));
|
||||
|
||||
des->add_node(tmp);
|
||||
des->add_signal(net);
|
||||
return net;
|
||||
}
|
||||
|
||||
/* None of the above tight constraints are present, so make a
|
||||
plausible choice for the width. Try to reduce the width as
|
||||
much as possible by eliminating high zeros of unsigned
|
||||
numbers. */
|
||||
unsigned width = value_->len();
|
||||
if ((lwidth > 0) && (lwidth < width))
|
||||
width = lwidth;
|
||||
|
||||
if (value_->has_sign() && (value_->get(width-1) == verinum::V0)) {
|
||||
|
||||
/* If the number is signed, but known to be positive,
|
||||
then reduce it down as if it were unsigned. */
|
||||
while (width > 1) {
|
||||
if (value_->get(width-1) != verinum::V0)
|
||||
break;
|
||||
width -= 1;
|
||||
}
|
||||
|
||||
} else if (value_->has_sign() == false) {
|
||||
while ( (width > 1) && (value_->get(width-1) == verinum::V0))
|
||||
width -= 1;
|
||||
}
|
||||
|
||||
verinum num (verinum::V0, width);
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
num.set(idx, value_->get(idx));
|
||||
|
||||
NetNet*net = new NetNet(0, des->local_symbol(path),
|
||||
NetNet::IMPLICIT, width);
|
||||
net->local_flag(true);
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1) {
|
||||
NetConst*tmp = new NetConst(des->local_symbol(path),
|
||||
value_->get(idx));
|
||||
des->add_node(tmp);
|
||||
connect(net->pin(idx), tmp->pin(0));
|
||||
}
|
||||
NetConst*tmp = new NetConst(des->local_symbol(path), num);
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(net->pin(idx), tmp->pin(idx));
|
||||
|
||||
des->add_node(tmp);
|
||||
des->add_signal(net);
|
||||
return net;
|
||||
}
|
||||
@@ -896,8 +1184,199 @@ NetNet* PETernary::elaborate_net(Design*des, const string&path,
|
||||
return sig;
|
||||
}
|
||||
|
||||
NetNet* PEUnary::elaborate_net(Design*des, const string&path,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const
|
||||
{
|
||||
NetNet* sub_sig = expr_->elaborate_net(des, path,
|
||||
op_=='~'?width:0,
|
||||
0, 0, 0);
|
||||
if (sub_sig == 0) {
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(sub_sig);
|
||||
|
||||
NetNet* sig;
|
||||
NetLogic*gate;
|
||||
switch (op_) {
|
||||
case '~': // Bitwise NOT
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE,
|
||||
sub_sig->pin_count());
|
||||
sig->local_flag(true);
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1) {
|
||||
gate = new NetLogic(des->local_symbol(path), 2,
|
||||
NetLogic::NOT);
|
||||
connect(gate->pin(1), sub_sig->pin(idx));
|
||||
connect(gate->pin(0), sig->pin(idx));
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
}
|
||||
des->add_signal(sig);
|
||||
break;
|
||||
|
||||
case 'N': // Reduction NOR
|
||||
case '!': // Reduction NOT
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::NOR);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
case '&': // Reduction AND
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::AND);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
case '|': // Reduction OR
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::OR);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
case '^': // Reduction XOR
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::XOR);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
case 'A': // Reduction NAND (~&)
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::NAND);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
|
||||
case 'X': // Reduction XNOR (~^)
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::XNOR);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << "internal error: Unhandled UNARY '" << op_ << "'" << endl;
|
||||
sig = 0;
|
||||
}
|
||||
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(sub_sig))
|
||||
delete tmp;
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.23 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.22 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.21 2000/02/14 06:04:52 steve
|
||||
* Unary reduction operators do not set their operand width
|
||||
*
|
||||
* Revision 1.20 2000/01/18 04:53:40 steve
|
||||
* Support structural XNOR.
|
||||
*
|
||||
* Revision 1.19 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.18 2000/01/11 04:20:57 steve
|
||||
* Elaborate net widths of constants to as small
|
||||
* as is possible, obeying context constraints.
|
||||
*
|
||||
* Comparison operators can handle operands with
|
||||
* different widths.
|
||||
*
|
||||
* Revision 1.17 2000/01/02 22:07:09 steve
|
||||
* Add a signal to nexus of padding constant.
|
||||
*
|
||||
* Revision 1.16 2000/01/02 21:45:31 steve
|
||||
* Add structural reduction NAND,
|
||||
* Fix size coercion of structural shifts.
|
||||
*
|
||||
* Revision 1.15 2000/01/02 19:39:03 steve
|
||||
* Structural reduction XNOR.
|
||||
*
|
||||
* Revision 1.14 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.13 1999/12/16 03:46:39 steve
|
||||
* Structural logical or.
|
||||
*
|
||||
* Revision 1.12 1999/12/16 02:42:14 steve
|
||||
* Simulate carry output on adders.
|
||||
*
|
||||
* Revision 1.11 1999/12/02 04:08:10 steve
|
||||
* Elaborate net repeat concatenations.
|
||||
*
|
||||
|
||||
+139
-180
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: elaborate.cc,v 1.132 1999/12/02 04:08:10 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elaborate.cc,v 1.145 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -228,6 +228,8 @@ void PGBuiltin::elaborate(Design*des, const string&path) const
|
||||
string name = get_name();
|
||||
if (name == "")
|
||||
name = des->local_symbol(path);
|
||||
else
|
||||
name = path+"."+name;
|
||||
|
||||
/* If the verilog source has a range specification for the
|
||||
gates, then I am expected to make more then one
|
||||
@@ -325,9 +327,14 @@ void PGBuiltin::elaborate(Design*des, const string&path) const
|
||||
case XOR:
|
||||
cur[idx] = new NetLogic(inm, pin_count(), NetLogic::XOR);
|
||||
break;
|
||||
default:
|
||||
cerr << get_line() << ": internal error: unhandled "
|
||||
"gate type." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
cur[idx]->set_attributes(attributes);
|
||||
cur[idx]->rise_time(rise_time);
|
||||
cur[idx]->fall_time(fall_time);
|
||||
cur[idx]->decay_time(decay_time);
|
||||
@@ -376,7 +383,24 @@ void PGBuiltin::elaborate(Design*des, const string&path) const
|
||||
*/
|
||||
void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const
|
||||
{
|
||||
// Missing module instance names have already been rejected.
|
||||
assert(get_name() != "");
|
||||
// Check for duplicate scopes.
|
||||
if (NetScope*tmp = des->find_scope(path + "." + get_name())) {
|
||||
cerr << get_line() << ": error: Instance/Scope name " <<
|
||||
get_name() << " already used in this context." <<
|
||||
endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (msb_) {
|
||||
cerr << get_line() << ": sorry: Module instantiation arrays "
|
||||
"are not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
NetScope*my_scope = des->make_scope(path, NetScope::MODULE, get_name());
|
||||
const string my_name = my_scope -> name();
|
||||
|
||||
@@ -447,7 +471,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const
|
||||
// elaboration causes the module to generate a netlist with
|
||||
// the ports represented by NetNet objects. I will find them
|
||||
// later.
|
||||
rmod->elaborate(des, my_scope, overrides_);
|
||||
rmod->elaborate(des, my_scope, parms_, nparms_, overrides_);
|
||||
|
||||
// Now connect the ports of the newly elaborated designs to
|
||||
// the expressions that are the instantiation parameters. Scan
|
||||
@@ -648,155 +672,6 @@ NetNet* PEConcat::elaborate_lnet(Design*des, const string&path) const
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PEUnary::elaborate_net(Design*des, const string&path,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const
|
||||
{
|
||||
NetNet* sub_sig = expr_->elaborate_net(des, path, width,
|
||||
0, 0, 0);
|
||||
if (sub_sig == 0) {
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(sub_sig);
|
||||
|
||||
NetNet* sig;
|
||||
NetLogic*gate;
|
||||
switch (op_) {
|
||||
case '~': // Bitwise NOT
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE,
|
||||
sub_sig->pin_count());
|
||||
sig->local_flag(true);
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1) {
|
||||
gate = new NetLogic(des->local_symbol(path), 2,
|
||||
NetLogic::NOT);
|
||||
connect(gate->pin(1), sub_sig->pin(idx));
|
||||
connect(gate->pin(0), sig->pin(idx));
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
}
|
||||
des->add_signal(sig);
|
||||
break;
|
||||
|
||||
case 'N': // Reduction NOR
|
||||
case '!': // Reduction NOT
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::NOR);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
case '&': // Reduction AND
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::AND);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
case '|': // Reduction OR
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::OR);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
case '^': // Reduction XOR
|
||||
sig = new NetNet(0, des->local_symbol(path), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(des->local_symbol(path),
|
||||
1+sub_sig->pin_count(),
|
||||
NetLogic::XOR);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
||||
des->add_signal(sig);
|
||||
des->add_node(gate);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << "internal error: Unhandled UNARY '" << op_ << "'" << endl;
|
||||
sig = 0;
|
||||
}
|
||||
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(sub_sig))
|
||||
delete tmp;
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
unsigned repeat = 1;
|
||||
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
if (repeat_) {
|
||||
verinum*vrep = repeat_->eval_const(des, path);
|
||||
if (vrep == 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = vrep->as_ulong();
|
||||
delete vrep;
|
||||
}
|
||||
|
||||
/* Make the empty concat expression. */
|
||||
NetEConcat*tmp = new NetEConcat(parms_.count(), repeat);
|
||||
tmp->set_line(*this);
|
||||
|
||||
/* Elaborate all the parameters and attach them to the concat node. */
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
assert(parms_[idx]);
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, path);
|
||||
if (ex == 0) continue;
|
||||
tmp->set(idx, parms_[idx]->elaborate_expr(des, path));
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PENumber::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
assert(value_);
|
||||
@@ -860,7 +735,7 @@ NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix,
|
||||
assert(rv);
|
||||
|
||||
rv->set_width(mem->width());
|
||||
NetExpr*idx = ix->elaborate_expr(des, path);
|
||||
NetNet*idx = ix->elaborate_net(des, path, 0, 0, 0, 0);
|
||||
assert(idx);
|
||||
|
||||
NetAssignMem*am = new NetAssignMem(mem, idx, rv);
|
||||
@@ -1170,7 +1045,7 @@ NetProc* PAssignNB::assign_to_memory_(NetMemory*mem, PExpr*ix,
|
||||
rv->set_width(mem->width());
|
||||
|
||||
/* Elaborate the expression to calculate the index, ... */
|
||||
NetExpr*idx = ix->elaborate_expr(des, path);
|
||||
NetNet*idx = ix->elaborate_net(des, path, 0, 0, 0, 0);
|
||||
assert(idx);
|
||||
|
||||
/* And connect them together in an assignment NetProc. */
|
||||
@@ -1227,7 +1102,7 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const
|
||||
|
||||
cur = new NetAssignNB(des->local_symbol(path), des, wid, rv);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(cur->pin(idx), reg->pin(idx+lsb));
|
||||
connect(cur->pin(idx), reg->pin(idx));
|
||||
|
||||
} else {
|
||||
assert(reg->pin_count() == 1);
|
||||
@@ -1263,9 +1138,22 @@ NetProc* PBlock::elaborate(Design*des, const string&path) const
|
||||
NetBlock*cur = new NetBlock(type);
|
||||
bool fail_flag = false;
|
||||
|
||||
string npath = name_.length()
|
||||
? des->make_scope(path, NetScope::BEGIN_END, name_) -> name()
|
||||
: path;
|
||||
string npath;
|
||||
if (name_.length()) {
|
||||
// Check for duplicate scopes.
|
||||
if (NetScope*tmp = des->find_scope(path + "." + name_)) {
|
||||
cerr << get_line() << ": error: Instance/Scope name " <<
|
||||
name_ << " already used in this context." <<
|
||||
endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
// Make this new scope.
|
||||
npath = des->make_scope(path, NetScope::BEGIN_END, name_)->name();
|
||||
|
||||
} else {
|
||||
npath = path;
|
||||
}
|
||||
|
||||
// Handle the special case that the block contains only one
|
||||
// statement. There is no need to keep the block node.
|
||||
@@ -1410,6 +1298,7 @@ NetProc* PCondit::elaborate(Design*des, const string&path) const
|
||||
NetProc*e = else_? else_->elaborate(des, path) : 0;
|
||||
|
||||
NetCondit*res = new NetCondit(expr, i, e);
|
||||
res->set_line(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1891,7 +1780,9 @@ NetProc* PWhile::elaborate(Design*des, const string&path) const
|
||||
return loop;
|
||||
}
|
||||
|
||||
bool Module::elaborate(Design*des, NetScope*scope, svector<PExpr*>*overrides_) const
|
||||
bool Module::elaborate(Design*des, NetScope*scope,
|
||||
named<PExpr*>*parms, unsigned nparms,
|
||||
svector<PExpr*>*overrides_) const
|
||||
{
|
||||
const string path = scope->name();
|
||||
bool result_flag = true;
|
||||
@@ -1903,33 +1794,62 @@ bool Module::elaborate(Design*des, NetScope*scope, svector<PExpr*>*overrides_) c
|
||||
// pass references them during elaboration.
|
||||
typedef map<string,PExpr*>::const_iterator mparm_it_t;
|
||||
|
||||
// So this loop elaborates the parameters, ...
|
||||
// So this loop elaborates the parameters, but doesn't
|
||||
// evaluate references to parameters. This scan practically
|
||||
// locates all the parameters and puts them in the parameter
|
||||
// table in the design. No expressions are evaluated.
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
string pname = path + "." + (*cur).first;
|
||||
des->set_parameter(pname, new NetEParam);
|
||||
}
|
||||
|
||||
// and this loop elaborates the expressions.
|
||||
// The replace map contains replacement expressions for the
|
||||
// parameters. If there is a replacement expression, use that
|
||||
// instead of the default expression. Otherwise, use the
|
||||
// default expression.
|
||||
|
||||
// Replacement expressions can come from the ordered list of
|
||||
// overrides, or from the parameter replace by name list.
|
||||
|
||||
map<string,PExpr*> replace;
|
||||
|
||||
if (overrides_) {
|
||||
assert(parms == 0);
|
||||
list<string>::const_iterator cur = param_names.begin();
|
||||
for (unsigned idx = 0
|
||||
; idx < overrides_->count()
|
||||
; idx += 1, cur++) {
|
||||
replace[*cur] = (*overrides_)[idx];
|
||||
}
|
||||
|
||||
} else if (parms) {
|
||||
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1)
|
||||
replace[parms[idx].name] = parms[idx].parm;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ... and this loop elaborates the expressions. The parameter
|
||||
// expressions are reduced to ordinary expressions that do not
|
||||
// include references to other parameters. Take careful note
|
||||
// of the fact that override expressions are elaborated in the
|
||||
// *parent* scope.
|
||||
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
string pname = path + "." + (*cur).first;
|
||||
NetExpr*expr = (*cur).second->elaborate_expr(des, path);
|
||||
NetExpr*expr;
|
||||
|
||||
if (PExpr*tmp = replace[(*cur).first])
|
||||
expr = tmp->elaborate_expr(des, scope->parent()->name());
|
||||
else
|
||||
expr = (*cur).second->elaborate_expr(des, path);
|
||||
|
||||
des->set_parameter(pname, expr);
|
||||
}
|
||||
|
||||
// Override parameters
|
||||
// FIXME: need to check if too many overrides given
|
||||
// FIXME: need to release the replaced expression.
|
||||
|
||||
if (overrides_) {
|
||||
list<string>::const_iterator cur = param_names.begin();
|
||||
for (unsigned idx = 0 ; idx < overrides_->count(); idx += 1, cur++) {
|
||||
string pname = path + "." + (*cur);
|
||||
NetExpr*expr = (*overrides_)[idx]->elaborate_expr(des, path);
|
||||
des->set_parameter(pname, expr);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, evaluate the parameter value. This step collapses
|
||||
// the parameters to NetEConst values.
|
||||
@@ -1972,13 +1892,13 @@ bool Module::elaborate(Design*des, NetScope*scope, svector<PExpr*>*overrides_) c
|
||||
|
||||
// Get all the explicitly declared wires of the module and
|
||||
// start the signals list with them.
|
||||
const list<PWire*>&wl = get_wires();
|
||||
const map<string,PWire*>&wl = get_wires();
|
||||
|
||||
for (list<PWire*>::const_iterator wt = wl.begin()
|
||||
for (map<string,PWire*>::const_iterator wt = wl.begin()
|
||||
; wt != wl.end()
|
||||
; wt ++ ) {
|
||||
|
||||
(*wt)->elaborate(des, scope);
|
||||
(*wt).second->elaborate(des, scope);
|
||||
}
|
||||
|
||||
// Elaborate functions.
|
||||
@@ -2076,7 +1996,7 @@ Design* elaborate(const map<string,Module*>&modules,
|
||||
|
||||
modlist = &modules;
|
||||
udplist = &primitives;
|
||||
bool rc = rmod->elaborate(des, scope, (svector<PExpr*>*)0);
|
||||
bool rc = rmod->elaborate(des, scope, 0, 0, (svector<PExpr*>*)0);
|
||||
modlist = 0;
|
||||
udplist = 0;
|
||||
|
||||
@@ -2090,6 +2010,45 @@ Design* elaborate(const map<string,Module*>&modules,
|
||||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.145 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.144 2000/02/18 05:15:02 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.143 2000/02/14 00:11:11 steve
|
||||
* Mark the line numbers of NetCondit nodes.
|
||||
*
|
||||
* Revision 1.142 2000/02/06 23:13:14 steve
|
||||
* Include the scope in named gates.
|
||||
*
|
||||
* Revision 1.141 2000/01/10 01:35:23 steve
|
||||
* Elaborate parameters afer binding of overrides.
|
||||
*
|
||||
* Revision 1.140 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.139 2000/01/09 05:50:48 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.138 2000/01/02 19:39:03 steve
|
||||
* Structural reduction XNOR.
|
||||
*
|
||||
* Revision 1.137 2000/01/02 18:25:37 steve
|
||||
* Do not overrun the pin index when the LSB != 0.
|
||||
*
|
||||
* Revision 1.136 2000/01/01 06:18:00 steve
|
||||
* Handle synthesis of concatenation.
|
||||
*
|
||||
* Revision 1.135 1999/12/14 23:42:16 steve
|
||||
* Detect duplicate scopes.
|
||||
*
|
||||
* Revision 1.134 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.133 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.132 1999/12/02 04:08:10 steve
|
||||
* Elaborate net repeat concatenations.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: emit.cc,v 1.31 1999/11/28 23:42:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: emit.cc,v 1.33 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -85,6 +85,11 @@ void NetFF::emit_node(ostream&o, struct target_t*tgt) const
|
||||
tgt->lpm_ff(o, this);
|
||||
}
|
||||
|
||||
void NetMult::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_mult(o, this);
|
||||
}
|
||||
|
||||
void NetMux::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_mux(o, this);
|
||||
@@ -389,6 +394,12 @@ bool emit(ostream&o, const Design*des, const char*type)
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.33 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.32 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.31 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-1999 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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: eval.cc,v 1.12 1999/11/30 04:48:17 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval.cc,v 1.13 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
@@ -142,6 +142,9 @@ verinum* PETernary::eval_const(const Design*des, const string&path) const
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.13 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.12 1999/11/30 04:48:17 steve
|
||||
* Handle evaluation of ternary during elaboration.
|
||||
*
|
||||
|
||||
+15
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: eval_tree.cc,v 1.6 1999/10/22 23:57:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval_tree.cc,v 1.8 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -138,6 +138,12 @@ NetEConst* NetEBLogic::eval_tree()
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBMult::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate the shift operator if possible. For this to work, both
|
||||
* operands must be constant.
|
||||
@@ -262,6 +268,12 @@ NetExpr* NetEParam::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.8 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.7 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.6 1999/10/22 23:57:53 steve
|
||||
* do the <= in bits, not numbers.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here we have the canonical "Hello, World" program written in Verilog.
|
||||
* We simply print to the program output a simple message. This example
|
||||
* demonstrates the process of compiling and executing a program with
|
||||
* Icarus Verilog.
|
||||
*
|
||||
* Compile this program with the command:
|
||||
*
|
||||
* verilog hello.vl
|
||||
*
|
||||
* After churning for a little while, the program will create the output
|
||||
* file "hello" which is compiled, linked and ready to run. Run this
|
||||
* program like so:
|
||||
*
|
||||
* ./hello
|
||||
*
|
||||
* and the program will print the message to its output. Easy!
|
||||
*/
|
||||
|
||||
module main();
|
||||
|
||||
initial
|
||||
begin
|
||||
$display("Hello, World");
|
||||
$finish ;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* IVL should generate an AND gate, and should make an OBUF and two
|
||||
* IBUF objects, along with the PAD objects.
|
||||
*
|
||||
* To compile this for XNF, try a command like this:
|
||||
*
|
||||
* verilog -X -fpart=XC4010XLPQ160 -fncf=outff.ncf outff.v
|
||||
*
|
||||
* That command causes an outff.xnf and outff.ncf file to be created.
|
||||
* Next, make the outff.ngd file with the command:
|
||||
*
|
||||
* xnf2ngd -l xilinxun -u outff.xnf outff.ngo
|
||||
* ngdbuild outff.ngo outff.ngd
|
||||
*
|
||||
* Finally, map the file to fully render it in the target part. The
|
||||
* par command is the step that actually optimizes the design and tries
|
||||
* to meet timing constraints.
|
||||
*
|
||||
* map -o map.ncd outff.ngd
|
||||
* par -w map.ncd outff.ncd
|
||||
*
|
||||
* At this point, you can use the FPGA Editor to edit the outff.ncd
|
||||
* file to see that the AND gate is in a CLB and the IOB for pin 150
|
||||
* has its flip-flop in use, and that gbuf is a global buffer.
|
||||
*/
|
||||
|
||||
module main;
|
||||
|
||||
wire clk, iclk;
|
||||
wire i0, i1;
|
||||
wire out;
|
||||
reg o0;
|
||||
|
||||
// This simple logic gate get turned into a function unit.
|
||||
// The par program will map this into a CLB F or G unit.
|
||||
and (out, i0, i1);
|
||||
|
||||
// This creates a global clock buffer. Notice how I attach an
|
||||
// attribute to the named gate to force it to be mapped to the
|
||||
// desired XNF device. This device will not be pulled into the
|
||||
// IOB associated with iclk because of the attribute.
|
||||
buf gbuf(clk, iclk);
|
||||
$attribute(gbuf, "XNF-LCA", "GCLK:O,I");
|
||||
|
||||
// This is mapped to a DFF. Since o0 is connected to a PAD, it
|
||||
// is turned into a OUTFF so that it get placed into an IOB.
|
||||
always @(posedge clk) o0 = out;
|
||||
|
||||
// These attribute commands assign pins to the listed wires.
|
||||
// This can be done to wires and registers, as internally both
|
||||
// are treated as named signals.
|
||||
$attribute(o0, "PAD", "o150");
|
||||
$attribute(i0, "PAD", "i152");
|
||||
$attribute(i1, "PAD", "i153");
|
||||
$attribute(iclk,"PAD", "i154");
|
||||
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example program simulates a 16x1 ram, and is used as an
|
||||
* example for using VCD output and waveform viewers.
|
||||
*
|
||||
* Like any other Verilog simulation, compile this program with the
|
||||
* command:
|
||||
*
|
||||
* verilog show_vcd.vl
|
||||
*
|
||||
* This will generate the show_vcd command in the current directory.
|
||||
* When you run the command, you will see the output from all the
|
||||
* calls to $display, but also there will be a dump file ``show_vcd.vcd''.
|
||||
* The name of this file is set by the statement:
|
||||
*
|
||||
* $dumpfile("show_vcd.vcd");
|
||||
*
|
||||
* in the main module. The output file uses the standard VCD file format
|
||||
* so can be viewed using off-the-shelf waveform viewers. The remaining
|
||||
* steps describe how to use GTKWave to view the file. If you are using
|
||||
* a different viewer, see the documentation for that tool.
|
||||
*
|
||||
* To view the output generated by running show_vcd, start the GTKWave
|
||||
* viewer with the command:
|
||||
*
|
||||
* wave show_vcd.vcd
|
||||
*
|
||||
* The GTKWave program will display its main window, and show in a small
|
||||
* status box (upper left corner) that it succeeded in loading the dump
|
||||
* file. However, there are no waveforms displayed yet. Select signals to
|
||||
* add to the waveform display using the menu selection:
|
||||
*
|
||||
* "Search --> Signal Search Tree"
|
||||
*
|
||||
* This will bring up a dialog box that shows in directory tree format
|
||||
* the signals of the program. Select the signals you wish to view, and
|
||||
* click one of the buttons on the bottom of the dialog box to display
|
||||
* the selected signals in the waveform window. Click "Exit" on the box
|
||||
* to get rid of it.
|
||||
*
|
||||
* The magic that makes all this work is contained in the $dumpfile and
|
||||
* $dumpvars system tasks. The $dumpfile task tells the simulation where
|
||||
* to write the VCD output. This task must be called once before the
|
||||
* $dumpvars task is called.
|
||||
*
|
||||
* The $dumpvars task tells the simulation what variables to write to
|
||||
* the VCD output. The first parameter is how far to descend while
|
||||
* scanning a scope, and the remaining paramters are signals or scope
|
||||
* names to include in the dump. If a scope name is given, all the
|
||||
* signals within the scope are dumped. If a wire or register name is
|
||||
* given, that signal is included.
|
||||
*/
|
||||
|
||||
module ram16x1 (q, d, a, we, wclk);
|
||||
output q;
|
||||
input d;
|
||||
input [3:0] a;
|
||||
input we;
|
||||
input wclk;
|
||||
|
||||
reg mem[15:0];
|
||||
|
||||
assign q = mem[a];
|
||||
always @(posedge wclk) if (we) mem[a] = d;
|
||||
|
||||
endmodule /* ram16x1 */
|
||||
|
||||
module main;
|
||||
wire q;
|
||||
reg d;
|
||||
reg [3:0] a;
|
||||
reg we, wclk;
|
||||
|
||||
ram16x1 r1 (q, d, a, we, wclk);
|
||||
|
||||
initial begin
|
||||
$dumpfile("show_vcd.vcd");
|
||||
$dumpvars(1, main.r1);
|
||||
wclk = 0;
|
||||
we = 1;
|
||||
for (a = 0 ; a < 4'hf ; a = a + 1) begin
|
||||
d = a[0];
|
||||
#1 wclk = 1;
|
||||
#1 wclk = 0;
|
||||
$display("r1[%x] == %b", a, q);
|
||||
end
|
||||
|
||||
for (a = 0 ; a < 4'hf ; a = a + 1)
|
||||
#1 if (q !== a[0]) begin
|
||||
$display("FAILED -- mem[%h] !== %b", a, a[0]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* $Id: sqrt.vl,v 1.1 1999/12/05 21:08:56 steve Exp $"
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module approximates the square root of an unsigned 32bit
|
||||
* number. The algorithm works by doing a bit-wise binary search.
|
||||
* Starting from the most significant bit, the accumulated value
|
||||
* tries to put a 1 in the bit position. If that makes the square
|
||||
* to big for the input, the bit is left zero, otherwise it is set
|
||||
* in the result. This continues for each bit, decreasing in
|
||||
* significance, until all the bits are calculated or all the
|
||||
* remaining bits are zero.
|
||||
*
|
||||
* Since the result is an integer, this function really calculates
|
||||
* value of the expression:
|
||||
*
|
||||
* x = floor(sqrt(y))
|
||||
*
|
||||
* where sqrt(y) is the exact square root of y and floor(N) is the
|
||||
* largest integer <= N.
|
||||
*
|
||||
* For 32bit numbers, this will never run more then 16 iterations,
|
||||
* which amounts to 16 clocks.
|
||||
*/
|
||||
|
||||
module sqrt32(clk, rdy, reset, x, .y(acc));
|
||||
input clk;
|
||||
output rdy;
|
||||
input reset;
|
||||
|
||||
input [31:0] x;
|
||||
output [15:0] acc;
|
||||
|
||||
|
||||
// acc holds the accumulated result, and acc2 is the accumulated
|
||||
// square of the accumulated result.
|
||||
reg [15:0] acc;
|
||||
reg [31:0] acc2;
|
||||
|
||||
// Keep track of which bit I'm working on.
|
||||
reg [4:0] bitl;
|
||||
wire [15:0] bit = 1 << bitl;
|
||||
wire [31:0] bit2 = 1 << (bitl << 1);
|
||||
|
||||
// The output is ready when the bitl counter underflows.
|
||||
wire rdy = bitl[4];
|
||||
|
||||
// guess holds the potential next values for acc, and guess2 holds
|
||||
// the square of that guess. The guess2 calculation is a little bit
|
||||
// subtle. The idea is that:
|
||||
//
|
||||
// guess2 = (acc + bit) * (acc + bit)
|
||||
// = (acc * acc) + 2*acc*bit + bit*bit
|
||||
// = acc2 + 2*acc*bit + bit2
|
||||
// = acc2 + 2 * (acc<<bitl) + bit
|
||||
//
|
||||
// This works out using shifts because bit and bit2 are known to
|
||||
// have only a single bit in them.
|
||||
wire [15:0] guess = acc | bit;
|
||||
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
|
||||
|
||||
task clear;
|
||||
begin
|
||||
acc = 0;
|
||||
acc2 = 0;
|
||||
bitl = 15;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial clear;
|
||||
|
||||
always @(reset or posedge clk)
|
||||
if (reset)
|
||||
clear;
|
||||
else begin
|
||||
if (guess2 <= x) begin
|
||||
acc <= guess;
|
||||
acc2 <= guess2;
|
||||
end
|
||||
bitl <= bitl - 1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module main;
|
||||
|
||||
reg clk, reset;
|
||||
reg [31:0] value;
|
||||
wire [15:0] result;
|
||||
wire rdy;
|
||||
|
||||
sqrt32 root(.clk(clk), .rdy(rdy), .reset(reset), .x(value), .y(result));
|
||||
|
||||
always #5 clk = ~clk;
|
||||
|
||||
always @(posedge rdy) begin
|
||||
$display("sqrt(%d) --> %d", value, result);
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
reset = 1;
|
||||
$monitor($time,,"%m = %b", root.acc, root.acc);
|
||||
#100 value = 63;
|
||||
reset = 0;
|
||||
end
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example demonstrates Icarus Verilog's ability to synthesize
|
||||
* efficient adders for Xilinx 4000 series FPGAs. The synthesis and
|
||||
* code generation makes an adder and translates that into XOR gates
|
||||
* and fast carry chain hardware.
|
||||
*
|
||||
* To compile this for XNF, try a command like this:
|
||||
*
|
||||
* verilog -X -fpart=XC4010XLPQ160 -fncf=xnf_add.ncf xnf_add.v
|
||||
*
|
||||
* That command causes an xnf_add.xnf and xnf_add.ncf file to be created.
|
||||
* Next, make the xnf_add.ngd file with the command:
|
||||
*
|
||||
* xnf2ngd -l xilinxun -u xnf_add.xnf xnf_add.ngo
|
||||
* ngdbuild xnf_add.ngo xnf_add.ngd
|
||||
*
|
||||
* Finally, map the file to fully render it in the target part. The
|
||||
* par command is the step that actually optimizes the design and tries
|
||||
* to meet timing constraints.
|
||||
*
|
||||
* map -o map.ncd xnf_add.ngd
|
||||
* par -w map.ncd xnf_add.ncd
|
||||
*
|
||||
* At this point, you can use the FPGA Editor to edit the xnf_add.ncd
|
||||
* file to see the carry chains made up to support the adder.
|
||||
*/
|
||||
|
||||
module main;
|
||||
|
||||
wire [3:0] a, b;
|
||||
wire [3:0] out;
|
||||
wire carry;
|
||||
|
||||
wire a0, a1, a2, a3, b0, b1, b2, b3;
|
||||
wire out0, out1, out2, out3;
|
||||
|
||||
// This creates the actual adder. Note that we also create a link
|
||||
// to the carry output. The principle adder is 4 bits wide, so two
|
||||
// IOBs are used to to the actual addition. PAR will place them in
|
||||
// order along carry lines. An extra carry cell from below a[0] is
|
||||
// used in FORCE-0 mode to load the bottom carry node.
|
||||
//
|
||||
// The carry signal from the top CY device is used to drive the
|
||||
// main.carry wire shown here. It is managed in this case by using
|
||||
// an ADD-FG-CI CY device for the top pair and using the CLB above
|
||||
// the carry chain, with its CY in EXAMINE-CI mode, to put the carry
|
||||
// out through its G function unit.
|
||||
|
||||
assign {carry, out} = a + b;
|
||||
|
||||
|
||||
// These attribute commands assign pins to the listed wires.
|
||||
// This can be done to wires and registers, as internally both
|
||||
// are treated as named signals. It doesn't work (yet) on vectors,
|
||||
// though, so break out the vectors with scaler assignments.
|
||||
|
||||
assign a[0] = a0;
|
||||
assign a[1] = a1;
|
||||
assign a[2] = a2;
|
||||
assign a[3] = a3;
|
||||
$attribute(a0, "PAD", "i150");
|
||||
$attribute(a1, "PAD", "i152");
|
||||
$attribute(a2, "PAD", "i153");
|
||||
$attribute(a3, "PAD", "i154");
|
||||
assign b[0] = b0;
|
||||
assign b[1] = b1;
|
||||
assign b[2] = b2;
|
||||
assign b[3] = b3;
|
||||
$attribute(b0, "PAD", "i155");
|
||||
$attribute(b1, "PAD", "i156");
|
||||
$attribute(b2, "PAD", "i157");
|
||||
$attribute(b3, "PAD", "i158");
|
||||
assign out0 = out[0];
|
||||
assign out1 = out[1];
|
||||
assign out2 = out[2];
|
||||
assign out3 = out[3];
|
||||
$attribute(out0, "PAD", "o71");
|
||||
$attribute(out1, "PAD", "o72");
|
||||
$attribute(out2, "PAD", "o73");
|
||||
$attribute(out3, "PAD", "o74");
|
||||
$attribute(carry, "PAD", "o75");
|
||||
|
||||
endmodule /* main */
|
||||
+49
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: expr_synth.cc,v 1.6 1999/11/28 23:42:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: expr_synth.cc,v 1.10 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -83,6 +83,7 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, lsig->pin_count());
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
string oname = des->local_symbol(path);
|
||||
@@ -119,18 +120,43 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConcat::synthesize(Design*des)
|
||||
{
|
||||
assert(repeat_ == 1);
|
||||
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, expr_width());
|
||||
osig->local_flag(true);
|
||||
|
||||
unsigned obit = 0;
|
||||
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*tmp = parms_[idx-1]->synthesize(des);
|
||||
|
||||
for (unsigned bit = 0 ; bit < tmp->pin_count() ; bit += 1) {
|
||||
connect(osig->pin(obit), tmp->pin(bit));
|
||||
obit += 1;
|
||||
}
|
||||
|
||||
if (tmp->local_flag())
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
des->add_signal(osig);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConst::synthesize(Design*des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
unsigned width=expr_width();
|
||||
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
string oname = des->local_symbol(path);
|
||||
NetConst *c = new NetConst(oname, value().get(idx));
|
||||
connect(osig->pin(idx), c->pin(0));
|
||||
des->add_node(c);
|
||||
}
|
||||
osig->local_flag(true);
|
||||
NetConst*con = new NetConst(des->local_symbol(path), value());
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1)
|
||||
connect(osig->pin(idx), con->pin(idx));
|
||||
|
||||
des->add_node(con);
|
||||
des->add_signal(osig);
|
||||
return osig;
|
||||
}
|
||||
@@ -145,6 +171,7 @@ NetNet* NetEUBits::synthesize(Design*des)
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, isig->pin_count());
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
string oname = des->local_symbol(path);
|
||||
@@ -179,6 +206,7 @@ NetNet* NetETernary::synthesize(Design *des)
|
||||
assert(tsig->pin_count() == fsig->pin_count());
|
||||
unsigned width=tsig->pin_count();
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
|
||||
string oname = des->local_symbol(path);
|
||||
NetMux *mux = new NetMux(oname, width, 2, 1);
|
||||
@@ -200,6 +228,18 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.10 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/01 06:18:00 steve
|
||||
* Handle synthesis of concatenation.
|
||||
*
|
||||
* Revision 1.8 1999/12/17 06:18:15 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.7 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.6 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
+84
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: functor.cc,v 1.5 1999/12/01 06:06:16 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: functor.cc,v 1.12 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "functor.h"
|
||||
@@ -35,10 +35,26 @@ void functor_t::process(class Design*, class NetProcTop*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_add_sub(class Design*, class NetAddSub*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_const(class Design*, class NetConst*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_ff(class Design*, class NetFF*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_logic(class Design*, class NetLogic*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_mult(class Design*, class NetMult*)
|
||||
{
|
||||
}
|
||||
|
||||
void Design::functor(functor_t*fun)
|
||||
{
|
||||
// apply to signals
|
||||
@@ -66,7 +82,7 @@ void Design::functor(functor_t*fun)
|
||||
NetNode*tmp = cur->node_next_;
|
||||
cur->functor_node(this, fun);
|
||||
cur = tmp;
|
||||
} while (cur != nodes_->node_next_);
|
||||
} while (nodes_ && cur != nodes_->node_next_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,11 +91,31 @@ void NetNode::functor_node(Design*, functor_t*)
|
||||
{
|
||||
}
|
||||
|
||||
void NetAddSub::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_add_sub(des, this);
|
||||
}
|
||||
|
||||
void NetConst::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_const(des, this);
|
||||
}
|
||||
|
||||
void NetFF::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_ff(des, this);
|
||||
}
|
||||
|
||||
void NetLogic::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_logic(des, this);
|
||||
}
|
||||
|
||||
void NetMult::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_mult(des, this);
|
||||
}
|
||||
|
||||
proc_match_t::~proc_match_t()
|
||||
{
|
||||
}
|
||||
@@ -99,6 +135,28 @@ int NetAssign::match_proc(proc_match_t*that)
|
||||
return that->assign(this);
|
||||
}
|
||||
|
||||
int proc_match_t::assign_mem(NetAssignMem*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetAssignMem::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->assign_mem(this);
|
||||
}
|
||||
|
||||
int proc_match_t::block(NetBlock*)
|
||||
{
|
||||
cerr << "default (failing) match for block" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetBlock::match_proc(proc_match_t*that)
|
||||
{
|
||||
cerr << "NetBlock::match_proc" << endl;
|
||||
return that->block(this);
|
||||
}
|
||||
|
||||
int proc_match_t::condit(NetCondit*)
|
||||
{
|
||||
return 0;
|
||||
@@ -106,6 +164,7 @@ int proc_match_t::condit(NetCondit*)
|
||||
|
||||
int NetCondit::match_proc(proc_match_t*that)
|
||||
{
|
||||
cerr << "NetCondit::match_proc" << endl;
|
||||
return that->condit(this);
|
||||
}
|
||||
|
||||
@@ -121,6 +180,27 @@ int NetPEvent::match_proc(proc_match_t*that)
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.12 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.11 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.10 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.9 2000/01/02 17:57:20 steve
|
||||
* Handle nodes running out during node scan.
|
||||
*
|
||||
* Revision 1.8 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.7 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.6 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.5 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __functor_H
|
||||
#define __functor_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: functor.h,v 1.3 1999/12/01 06:06:16 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: functor.h,v 1.9 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -42,21 +42,53 @@ struct functor_t {
|
||||
/* This method is called for each process in the design. */
|
||||
virtual void process(class Design*des, class NetProcTop*);
|
||||
|
||||
/* This method is called for each structural adder. */
|
||||
virtual void lpm_add_sub(class Design*des, class NetAddSub*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_const(class Design*des, class NetConst*);
|
||||
|
||||
/* This method is called for each FF in the design. */
|
||||
virtual void lpm_ff(class Design*des, class NetFF*);
|
||||
|
||||
/* Handle LPM combinational logic devices. */
|
||||
virtual void lpm_logic(class Design*des, class NetLogic*);
|
||||
|
||||
/* This method is called for each multiplier. */
|
||||
virtual void lpm_mult(class Design*des, class NetMult*);
|
||||
};
|
||||
|
||||
struct proc_match_t {
|
||||
virtual ~proc_match_t();
|
||||
|
||||
virtual int assign(class NetAssign*);
|
||||
virtual int assign_mem(class NetAssignMem*);
|
||||
virtual int condit(class NetCondit*);
|
||||
virtual int pevent(class NetPEvent*);
|
||||
virtual int block(class NetBlock*);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.9 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.8 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.7 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.6 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.5 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.4 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.3 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
|
||||
+419
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* gverilog.c - A driver for verilog compiler ivl
|
||||
* Copyright (C) 1999 Stefan Petersen (spe@geda.seul.org)
|
||||
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifndef LIBDIR
|
||||
# define LIBDIR "/usr/local/lib"
|
||||
#endif
|
||||
#ifndef INCLUDEDIR
|
||||
# define INCLUDEDIR "/usr/local/include"
|
||||
#endif
|
||||
|
||||
const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
|
||||
#ifndef PATHLEN
|
||||
# define PATHLEN 100
|
||||
#endif
|
||||
|
||||
#define P_IF_SET(var) var.set ? var.name : ""
|
||||
|
||||
/* Div compiler settings */
|
||||
struct compset {
|
||||
char compsw[5];
|
||||
char name[PATHLEN];
|
||||
int set;
|
||||
};
|
||||
|
||||
/* cpp include path */
|
||||
struct compset cppincpath = {"-I", INCLUDEDIR, 1};
|
||||
|
||||
/* cpp library path */
|
||||
struct compset cpplibpath ={"-L", LIBDIR, 1};
|
||||
|
||||
/* VPI module path */
|
||||
struct compset VPImodpath = {"-f", LIBDIR "/ivl", 1};
|
||||
|
||||
/* ivl include path */
|
||||
struct compset ivlppincpath = {"-I", "", 0};
|
||||
|
||||
/* ivl defines */
|
||||
struct compset ivlppdefines = {"-D", "", 0};
|
||||
|
||||
/* ivl target setup */
|
||||
/* Compilation target, default vvm */
|
||||
typedef enum {VVM, XNF, NULLT, OTHER} targettype;
|
||||
struct target {
|
||||
targettype target;
|
||||
struct compset targetinfo;
|
||||
};
|
||||
struct target target = {VVM, {"-t", "vvm", 0}};
|
||||
|
||||
|
||||
/* functors setup */
|
||||
struct compset functors = {"-F","", 0};
|
||||
|
||||
/* output file */
|
||||
struct compset outputfile = {"-o", "", 0};
|
||||
|
||||
/* topmodule name */
|
||||
struct compset topmodule = {"-s", "", 0};
|
||||
|
||||
/* verilog files */
|
||||
char verilogfiles[PATHLEN] = "";
|
||||
|
||||
|
||||
/* Temp files for storage */
|
||||
char tmpPPfile[50];
|
||||
char tmpCCfile[50];
|
||||
|
||||
/* Compilation flag info */
|
||||
struct compileinfo {
|
||||
int pform;
|
||||
int execute;
|
||||
int elabnetlist;
|
||||
int debug;
|
||||
};
|
||||
struct compileinfo compileinfo = {0, 0, 0, 0};
|
||||
|
||||
|
||||
void sorry(char optelem)
|
||||
{
|
||||
printf("Sorry, switch -%c not implemented yet!\n", optelem);
|
||||
}
|
||||
|
||||
|
||||
void strchk(char *str, unsigned int maxlen)
|
||||
{
|
||||
if (strlen(str) >= maxlen)
|
||||
fprintf(stderr, "Warning! Following path too long, truncating it!\n%s\n",
|
||||
str);
|
||||
}
|
||||
|
||||
|
||||
targettype resolvtarget(char *target)
|
||||
{
|
||||
if (strcmp(target, "vvm") == 0) {
|
||||
return VVM;
|
||||
} else if (strcmp(target, "xnf") == 0) {
|
||||
sprintf(functors.name, "%ssynth %snodangle %sxnfio",
|
||||
functors.compsw, functors.compsw, functors.compsw);
|
||||
functors.set = 1;
|
||||
return XNF;
|
||||
} else if (strcmp(target, "null") == 0) {
|
||||
return NULLT;
|
||||
} else {
|
||||
return OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void error_exit(void)
|
||||
{
|
||||
fprintf(stderr, "verilog [-Dmacro[=defn]] [-Iincludepath] [-X] \n");
|
||||
fprintf(stderr, "[-x] [-o outputfilename] [-s topmodule] sourcefile[s]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void create_outputfilename(char *input, char *output)
|
||||
{
|
||||
char *dotpos, *spacepos;
|
||||
|
||||
if ((dotpos = strrchr(input, (int)'.')) == NULL) {
|
||||
dotpos = input + strlen(input);
|
||||
}
|
||||
|
||||
if ((spacepos = strrchr(input, (int)' ')) == NULL) {
|
||||
spacepos = input;
|
||||
}
|
||||
|
||||
output = strncpy(output, spacepos, dotpos-spacepos);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void preprocess(void)
|
||||
{
|
||||
char *argument;
|
||||
|
||||
argument = (char *)malloc(256);
|
||||
|
||||
sprintf(argument, LIBDIR "/ivl/ivlpp %s %s -L -o%s %s",
|
||||
P_IF_SET(ivlppdefines),
|
||||
P_IF_SET(ivlppincpath),
|
||||
tmpPPfile,
|
||||
verilogfiles);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Executing command : \n%s\n", argument);
|
||||
} else {
|
||||
if (system(argument)) {
|
||||
fprintf(stderr, "Preprocessing failed. Terminating compilation\n");
|
||||
unlink(tmpPPfile);
|
||||
free(argument);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
free(argument);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void compile(void)
|
||||
{
|
||||
char *argument;
|
||||
|
||||
argument = (char *)malloc(256);
|
||||
|
||||
/* VPI_MODULE_PATH should be better integrated. */
|
||||
/* HACK */
|
||||
sprintf(argument, LIBDIR "/ivl/ivl %s %s %s %sVPI_MODULE_PATH=%s -o %s %s",
|
||||
P_IF_SET(topmodule),
|
||||
target.targetinfo.compsw, target.targetinfo.name,
|
||||
VPImodpath.compsw, VPImodpath.name,
|
||||
/* compileinfo.pform ? "-P whatever_pform" : "",
|
||||
compileinfo.elabnetlist ? "-E whatever_netlist" : "", */
|
||||
tmpCCfile,
|
||||
tmpPPfile);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Executing command : \n%s\n", argument);
|
||||
printf("Removing file %s\n", tmpPPfile);
|
||||
} else {
|
||||
if (system(argument)) {
|
||||
fprintf(stderr, "Compilation failed. Terminating compilation\n");
|
||||
unlink(tmpCCfile);
|
||||
free(argument);
|
||||
exit(1);
|
||||
}
|
||||
unlink(tmpPPfile);
|
||||
}
|
||||
|
||||
free(argument);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void postprocess(void)
|
||||
{
|
||||
char *argument;
|
||||
|
||||
/* Hopefully not filling stack with large array */
|
||||
argument = malloc(256);
|
||||
|
||||
switch (target.target) {
|
||||
case VVM: /* Compile C++ source */
|
||||
|
||||
sprintf(argument, "g++ -rdynamic %s%s %s%s %s -o %s -lvvm -ldl",
|
||||
cppincpath.compsw, cppincpath.name, /* Include dir */
|
||||
cpplibpath.compsw, cpplibpath.name, /* Library dir */
|
||||
tmpCCfile,
|
||||
outputfile.name);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Executing command :\n%s\n", argument);
|
||||
} else {
|
||||
if (system(argument)) {
|
||||
fprintf(stderr, "g++ compilation failed. Terminating compilation\n");
|
||||
unlink(tmpCCfile);
|
||||
free(argument);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
unlink(tmpCCfile);
|
||||
break;
|
||||
case XNF: /* Just move file as is */
|
||||
sprintf(outputfile.name, "%s.xnf", outputfile.name);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Moving file %s to %s\n", tmpCCfile, outputfile.name);
|
||||
} else {
|
||||
if (rename(tmpCCfile, outputfile.name) == -1) {
|
||||
perror("Failed moving file. gverilog:postprocess\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NULLT: /* Remove file we accidently created */
|
||||
unlink(tmpCCfile);
|
||||
break;
|
||||
case OTHER: /* Just move file as is */
|
||||
sprintf(outputfile.name, "%s.%s", outputfile.name, target.targetinfo.name);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Moving file %s to %s\n", tmpCCfile, outputfile.name);
|
||||
} else {
|
||||
if (rename(tmpCCfile, outputfile.name) == -1) {
|
||||
perror("Failed moving file. gverilog:postprocess\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Illegal target. This should never happen.\n");
|
||||
error_exit();
|
||||
}
|
||||
|
||||
if (compileinfo.execute) {
|
||||
if (compileinfo.debug) {
|
||||
printf("Executing command :\n%s\n", outputfile.name);
|
||||
} else {
|
||||
system(outputfile.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(argument);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char optstring[] = "D:I:Xxf:o:s:t:EPvd";
|
||||
int optelem = 0;
|
||||
|
||||
|
||||
while ((optelem = getopt(argc, argv, optstring)) != EOF) {
|
||||
|
||||
switch ((char)optelem) {
|
||||
case 'D': /* defines */
|
||||
sprintf(ivlppdefines.name, "%s %s%s", ivlppdefines.name,
|
||||
ivlppdefines.compsw, optarg);
|
||||
ivlppdefines.set =1;
|
||||
break;
|
||||
case 'I': /* includepath */
|
||||
sprintf(ivlppincpath.name, "%s %s %s", ivlppincpath.name,
|
||||
ivlppincpath.compsw, optarg);
|
||||
ivlppincpath.set = 1;
|
||||
strchk(ivlppincpath.name, PATHLEN);
|
||||
break;
|
||||
case 'X': /* xnf target */
|
||||
if (target.targetinfo.set)
|
||||
fprintf(stderr, "Target already set to %s\n", target.targetinfo.name);
|
||||
else {
|
||||
sprintf(target.targetinfo.name,"%s xnf", target.targetinfo.compsw);
|
||||
target.targetinfo.set = 1;
|
||||
target.target = XNF;
|
||||
}
|
||||
break;
|
||||
case 'x': /* execute */
|
||||
compileinfo.execute = 1;
|
||||
break;
|
||||
case 'f': /* flags? */
|
||||
sorry((char)optelem);
|
||||
break;
|
||||
case 'o': /* output file */
|
||||
if (outputfile.set)
|
||||
fprintf(stderr, "Output filename already set to %s\n",
|
||||
outputfile.name);
|
||||
else {
|
||||
sprintf(outputfile.name, "%s", optarg);
|
||||
outputfile.set = 1;
|
||||
}
|
||||
break;
|
||||
case 's': /* top module */
|
||||
if (topmodule.set)
|
||||
fprintf(stderr, "Topmodule name already set to %s\n", topmodule.name);
|
||||
else {
|
||||
sprintf(topmodule.name, "%s %s", topmodule.compsw, optarg);
|
||||
topmodule.set = 1 ;
|
||||
}
|
||||
break;
|
||||
case 't': /* code target */
|
||||
if (target.targetinfo.set)
|
||||
fprintf(stderr, "Target already set to %s\n", target.targetinfo.name);
|
||||
else {
|
||||
sprintf(target.targetinfo.name, "%s", optarg);
|
||||
target.targetinfo.set = 1;
|
||||
target.target = resolvtarget(target.targetinfo.name);
|
||||
}
|
||||
break;
|
||||
case 'E': /* elaborated netlist */
|
||||
compileinfo.elabnetlist = 1;
|
||||
break;
|
||||
case 'P': /* dump pform */
|
||||
compileinfo.pform = 1;
|
||||
break;
|
||||
case 'v':
|
||||
printf("gverilog version %s\n", VERSION);
|
||||
system("ivlpp -v");
|
||||
printf("*****\n");
|
||||
system("ivl -v");
|
||||
printf("*****\n");
|
||||
system("g++ -v");
|
||||
return(0);
|
||||
case 'd':
|
||||
compileinfo.debug = 1;
|
||||
break;
|
||||
case '?':
|
||||
fprintf(stderr, "Not defined commandswitch %s\n", argv[optind]);
|
||||
error_exit();
|
||||
default:
|
||||
fprintf(stderr, "Not handled commandswitch %s\n", argv[optind]);
|
||||
error_exit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (optind == argc){
|
||||
fprintf(stderr, "Missing infile(s)\n");
|
||||
error_exit();
|
||||
}
|
||||
|
||||
/* Resolve temporary file storage */
|
||||
sprintf(tmpPPfile, "ivl%d.pp", (int)getpid());
|
||||
sprintf(tmpCCfile, "ivl%d.cc", (int)getpid());
|
||||
|
||||
/* Build list of verilog files */
|
||||
for(; optind != argc; optind++) {
|
||||
sprintf(verilogfiles, "%s %s", verilogfiles, argv[optind]);
|
||||
}
|
||||
strchk(verilogfiles , PATHLEN);
|
||||
|
||||
/* Determine output filename if not explicitly set */
|
||||
if (!outputfile.set) {
|
||||
create_outputfilename(verilogfiles, outputfile.name);
|
||||
}
|
||||
|
||||
|
||||
preprocess();
|
||||
|
||||
compile();
|
||||
|
||||
postprocess();
|
||||
|
||||
return(0);
|
||||
}
|
||||
+6
-6
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.6 1999/10/16 20:48:15 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.7 2000/01/01 20:57:51 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -60,16 +60,16 @@ lexor.c: lexor.lex
|
||||
parse.h parse.c: parse.y
|
||||
bison --verbose -t -d parse.y -o parse.c
|
||||
|
||||
install: all installdirs $(bindir)/ivlpp
|
||||
install: all installdirs $(libdir)/ivl/ivlpp
|
||||
|
||||
$(bindir)/ivlpp: ivlpp
|
||||
$(INSTALL_PROGRAM) ./ivlpp $(bindir)/ivlpp
|
||||
$(libdir)/ivl/ivlpp: ivlpp
|
||||
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir)
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/ivlpp
|
||||
rm -f $(libdir)/ivl/ivlpp
|
||||
|
||||
lexor.o: lexor.c parse.h globals.h
|
||||
main.o: main.c globals.h
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: lexor.lex,v 1.38 1999/11/23 02:49:04 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.42 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
//# define YYSTYPE lexval
|
||||
@@ -97,6 +97,7 @@ W [ \t\b\f\r]+
|
||||
"~^" { return K_NXOR; }
|
||||
"^~" { return K_NXOR; }
|
||||
"~&" { return K_NAND; }
|
||||
"->" { return K_TRIGGER; }
|
||||
|
||||
|
||||
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
|
||||
@@ -159,26 +160,26 @@ W [ \t\b\f\r]+
|
||||
yylval.text = strdup(cp);
|
||||
return PORTNAME; }
|
||||
|
||||
[0-9][0-9_]*[ \t]*\'[dD][ \t]*[0-9][0-9_]* {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[dD][ \t]*[0-9][0-9_]* {
|
||||
yylval.number = make_sized_dec(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[bB][ \t]*[0-1xzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ {
|
||||
yylval.number = make_sized_binary(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[oO][ \t]*[0-7xzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ {
|
||||
yylval.number = make_sized_octal(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ {
|
||||
yylval.number = make_sized_hex(yytext);
|
||||
return NUMBER; }
|
||||
|
||||
\'d[ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return NUMBER; }
|
||||
\'[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return NUMBER; }
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
return NUMBER; }
|
||||
\'[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
return NUMBER; }
|
||||
\'[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
return NUMBER; }
|
||||
|
||||
[0-9][0-9_]* {
|
||||
@@ -198,6 +199,7 @@ W [ \t\b\f\r]+
|
||||
}
|
||||
|
||||
yylval.number = new verinum(bits, nbits, false);
|
||||
yylval.number->has_sign(true);
|
||||
delete[]bits;
|
||||
return NUMBER; }
|
||||
|
||||
@@ -312,22 +314,26 @@ void lex_end_table()
|
||||
|
||||
static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
{
|
||||
assert(tolower(*ptr) == 'b');
|
||||
bool sign_flag = false;
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
|
||||
if (tolower(ptr[0]) == 's') {
|
||||
ptr += 1;
|
||||
sign_flag = true;
|
||||
}
|
||||
assert(tolower(*ptr) == 'b');
|
||||
ptr += 1;
|
||||
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
|
||||
unsigned idx = 0;
|
||||
const char*eptr = ptr + strlen(ptr) - 1;
|
||||
while ((eptr > ptr) && (idx < size)) {
|
||||
|
||||
if (*eptr == '_') {
|
||||
eptr -= 1;
|
||||
continue;
|
||||
}
|
||||
while ((eptr >= ptr) && (idx < size)) {
|
||||
|
||||
switch (*eptr) {
|
||||
case '_':
|
||||
break;
|
||||
case '0':
|
||||
bits[idx++] = verinum::V0;
|
||||
break;
|
||||
@@ -349,7 +355,7 @@ static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
// Zero-extend binary number, except that z or x is extended
|
||||
// if it is the highest supplied digit.
|
||||
while (idx < size) {
|
||||
switch (ptr[1]) {
|
||||
switch (ptr[0]) {
|
||||
case '0':
|
||||
case '1':
|
||||
bits[idx++] = verinum::V0;
|
||||
@@ -365,7 +371,10 @@ static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
}
|
||||
}
|
||||
|
||||
return new verinum(bits, size, fixed);
|
||||
verinum*out = new verinum(bits, size, fixed);
|
||||
delete[]bits;
|
||||
out->has_sign(sign_flag);
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_binary(const char*txt)
|
||||
@@ -376,16 +385,21 @@ static verinum*make_sized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
assert(tolower(*ptr) == 'b');
|
||||
|
||||
return make_binary_with_size(size, true, ptr);
|
||||
}
|
||||
|
||||
static verinum*make_unsized_binary(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'b');
|
||||
while (*ptr && ((*ptr == 'b') || (*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
@@ -420,17 +434,27 @@ static verinum*make_unsized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_octal(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
char*ptr;
|
||||
|
||||
unsigned size = strtoul(txt,&ptr,10);
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'o');
|
||||
|
||||
/* We know from the size number how bit to make the verinom
|
||||
@@ -506,14 +530,24 @@ static verinum*make_sized_octal(const char*txt)
|
||||
}
|
||||
}
|
||||
|
||||
return new verinum(bits, size, true);
|
||||
verinum*out = new verinum(bits, size, true);
|
||||
delete[]bits;
|
||||
out->has_sign(sign_flag);
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_unsized_octal(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
assert(tolower(*ptr) == 'o');
|
||||
ptr += 1;
|
||||
|
||||
@@ -555,11 +589,15 @@ static verinum*make_unsized_octal(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_hex(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
char*ptr;
|
||||
unsigned size = strtoul(txt,&ptr,10);
|
||||
|
||||
@@ -568,6 +606,12 @@ static verinum*make_sized_hex(const char*txt)
|
||||
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
assert(tolower(*ptr) == 'h');
|
||||
|
||||
ptr += 1;
|
||||
@@ -634,14 +678,23 @@ static verinum*make_sized_hex(const char*txt)
|
||||
bits[idx++] = verinum::V0;
|
||||
}
|
||||
|
||||
return new verinum(bits, size, true);
|
||||
verinum*out = new verinum(bits, size, true);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_unsized_hex(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'h');
|
||||
|
||||
ptr += 1;
|
||||
@@ -694,7 +747,10 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -703,6 +759,11 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
*/
|
||||
static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
{
|
||||
bool signed_flag = false;
|
||||
if (tolower(*ptr) == 's') {
|
||||
signed_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'd');
|
||||
|
||||
ptr += 1;
|
||||
@@ -726,7 +787,10 @@ static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
value /= 2;
|
||||
}
|
||||
|
||||
return new verinum(bits, size, fixed);
|
||||
verinum*out = new verinum(bits, size, fixed);
|
||||
out->has_sign(signed_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_dec(const char*txt)
|
||||
@@ -739,7 +803,6 @@ static verinum*make_sized_dec(const char*txt)
|
||||
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
assert(tolower(*ptr) == 'd');
|
||||
|
||||
return make_dec_with_size(size, true, ptr);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-1999 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1998-2000 Stephen Williams ([email protected])";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -18,8 +18,8 @@ const char COPYRIGHT[] =
|
||||
* 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)
|
||||
#ident "$Id: main.cc,v 1.26 1999/11/29 17:02:21 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: main.cc,v 1.29 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
const char NOTICE[] =
|
||||
@@ -81,7 +81,6 @@ extern Design* elaborate(const map<string,Module*>&modules,
|
||||
|
||||
extern void cprop(Design*des);
|
||||
extern void propinit(Design*des);
|
||||
extern void sigfold(Design*des);
|
||||
extern void synth(Design*des);
|
||||
extern void nobufz(Design*des);
|
||||
extern void nodangle(Design*des);
|
||||
@@ -97,7 +96,6 @@ static struct net_func_map {
|
||||
{ "nobufz", &nobufz },
|
||||
{ "nodangle",&nodangle },
|
||||
{ "propinit",&propinit },
|
||||
{ "sigfold", &sigfold },
|
||||
{ "synth", &synth },
|
||||
{ "xnfio", &xnfio },
|
||||
{ "xnfsyn", &xnfsyn },
|
||||
@@ -124,7 +122,9 @@ int main(int argc, char*argv[])
|
||||
unsigned flag_errors = 0;
|
||||
queue<net_func> net_func_queue;
|
||||
|
||||
while ((opt = getopt(argc, argv, "F:f:hN:o:P:s:t:v")) != EOF) switch (opt) {
|
||||
flags["VPI_MODULE_LIST"] = "system";
|
||||
|
||||
while ((opt = getopt(argc, argv, "F:f:hm:N:o:P:s:t:v")) != EOF) switch (opt) {
|
||||
case 'F': {
|
||||
net_func tmp = name_to_net_func(optarg);
|
||||
if (tmp == 0) {
|
||||
@@ -142,6 +142,9 @@ int main(int argc, char*argv[])
|
||||
case 'h':
|
||||
help_flag = true;
|
||||
break;
|
||||
case 'm':
|
||||
flags["VPI_MODULE_LIST"] = flags["VPI_MODULE_LIST"]+","+optarg;
|
||||
break;
|
||||
case 'N':
|
||||
net_path = optarg;
|
||||
break;
|
||||
@@ -284,6 +287,15 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.29 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.28 2000/01/13 05:11:25 steve
|
||||
* Support for multiple VPI modules.
|
||||
*
|
||||
* Revision 1.27 1999/12/30 17:37:14 steve
|
||||
* Remove the now useless sigfold functor.
|
||||
*
|
||||
* Revision 1.26 1999/11/29 17:02:21 steve
|
||||
* include getopt if present.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: mangle.cc,v 1.2 1999/02/15 05:52:50 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: mangle.cc,v 1.3 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -63,6 +63,9 @@ string mangle(const string&str)
|
||||
|
||||
/*
|
||||
* $Log: mangle.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/02/15 05:52:50 steve
|
||||
* Mangle that handles device instance numbers.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef __named_H
|
||||
#define __named_H
|
||||
/*
|
||||
* 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: named.h,v 1.2 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
||||
/*
|
||||
* There are lots of places where names are attached to objects. This
|
||||
* simple template expresses the lot.
|
||||
*/
|
||||
|
||||
template <class T> struct named {
|
||||
string name;
|
||||
T parm;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: named.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+311
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: netlist.cc,v 1.97 1999/12/02 16:58:58 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netlist.cc,v 1.105 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
@@ -145,7 +145,7 @@ bool NetObj::Link::is_linked(const NetObj&that) const
|
||||
bool NetObj::Link::is_linked(const NetObj::Link&that) const
|
||||
{
|
||||
for (const Link*idx = next_ ; this != idx ; idx = idx->next_)
|
||||
if (idx == &that)
|
||||
if (idx->is_equal(that))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -642,6 +642,16 @@ unsigned NetAddSub::width()const
|
||||
return (pin_count() - 6) / 3;
|
||||
}
|
||||
|
||||
NetObj::Link& NetAddSub::pin_Cout()
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
const NetObj::Link& NetAddSub::pin_Cout() const
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
NetObj::Link& NetAddSub::pin_DataA(unsigned idx)
|
||||
{
|
||||
idx = 6 + idx*3;
|
||||
@@ -922,6 +932,126 @@ const NetObj::Link& NetCompare::pin_DataB(unsigned idx) const
|
||||
return pin(8+width_+idx);
|
||||
}
|
||||
|
||||
NetMult::NetMult(const string&n, unsigned wr, unsigned wa, unsigned wb,
|
||||
unsigned ws)
|
||||
: NetNode(n, 2+wr+wa+wb+ws), width_r_(wr), width_a_(wa), width_b_(wb),
|
||||
width_s_(ws)
|
||||
{
|
||||
pin(0).set_dir(NetObj::Link::INPUT); pin(0).set_name("Aclr", 0);
|
||||
pin(1).set_dir(NetObj::Link::INPUT); pin(1).set_name("Clock", 0);
|
||||
|
||||
|
||||
unsigned p = 2;
|
||||
for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(NetObj::Link::OUTPUT);
|
||||
pin(p).set_name("Result", idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(NetObj::Link::INPUT);
|
||||
pin(p).set_name("DataA", idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(NetObj::Link::INPUT);
|
||||
pin(p).set_name("DataB", idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_s_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(NetObj::Link::INPUT);
|
||||
pin(p).set_name("Sum", idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetMult::~NetMult()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetMult::width_r() const
|
||||
{
|
||||
return width_r_;
|
||||
}
|
||||
|
||||
unsigned NetMult::width_a() const
|
||||
{
|
||||
return width_a_;
|
||||
}
|
||||
|
||||
unsigned NetMult::width_b() const
|
||||
{
|
||||
return width_b_;
|
||||
}
|
||||
|
||||
unsigned NetMult::width_s() const
|
||||
{
|
||||
return width_s_;
|
||||
}
|
||||
|
||||
NetObj::Link& NetMult::pin_Aclr()
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const NetObj::Link& NetMult::pin_Aclr() const
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
NetObj::Link& NetMult::pin_Clock()
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const NetObj::Link& NetMult::pin_Clock() const
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
NetObj::Link& NetMult::pin_Result(unsigned idx)
|
||||
{
|
||||
assert(idx < width_r_);
|
||||
return pin(idx+2);
|
||||
}
|
||||
|
||||
const NetObj::Link& NetMult::pin_Result(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_r_);
|
||||
return pin(idx+2);
|
||||
}
|
||||
|
||||
NetObj::Link& NetMult::pin_DataA(unsigned idx)
|
||||
{
|
||||
assert(idx < width_a_);
|
||||
return pin(idx+2+width_r_);
|
||||
}
|
||||
|
||||
const NetObj::Link& NetMult::pin_DataA(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_a_);
|
||||
return pin(idx+2+width_r_);
|
||||
}
|
||||
|
||||
NetObj::Link& NetMult::pin_DataB(unsigned idx)
|
||||
{
|
||||
assert(idx < width_b_);
|
||||
return pin(idx+2+width_r_+width_a_);
|
||||
}
|
||||
|
||||
const NetObj::Link& NetMult::pin_DataB(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_b_);
|
||||
return pin(idx+2+width_r_+width_a_);
|
||||
}
|
||||
|
||||
NetObj::Link& NetMult::pin_Sum(unsigned idx)
|
||||
{
|
||||
assert(idx < width_s_);
|
||||
return pin(idx+2+width_r_+width_a_+width_b_);
|
||||
}
|
||||
|
||||
const NetObj::Link& NetMult::pin_Sum(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_s_);
|
||||
return pin(idx+2+width_r_+width_a_+width_b_);
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetMux class represents an LPM_MUX device. The pinout is assigned
|
||||
* like so:
|
||||
@@ -1052,10 +1182,25 @@ NetRamDq::NetRamDq(const string&n, NetMemory*mem, unsigned awid)
|
||||
pin(3+awidth_+width()+idx).set_dir(NetObj::Link::OUTPUT);
|
||||
pin(3+awidth_+width()+idx).set_name("Q", idx);
|
||||
}
|
||||
|
||||
next_ = mem_->ram_list_;
|
||||
mem_->ram_list_ = this;
|
||||
}
|
||||
|
||||
NetRamDq::~NetRamDq()
|
||||
{
|
||||
if (mem_->ram_list_ == this) {
|
||||
mem_->ram_list_ = next_;
|
||||
|
||||
} else {
|
||||
NetRamDq*cur = mem_->ram_list_;
|
||||
while (cur->next_ != this) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
assert(cur->next_ == this);
|
||||
cur->next_ = next_;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetRamDq::width() const
|
||||
@@ -1078,6 +1223,82 @@ const NetMemory* NetRamDq::mem() const
|
||||
return mem_;
|
||||
}
|
||||
|
||||
unsigned NetRamDq::count_partners() const
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (NetRamDq*cur = mem_->ram_list_ ; cur ; cur = cur->next_)
|
||||
count += 1;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void NetRamDq::absorb_partners()
|
||||
{
|
||||
NetRamDq*cur, *tmp;
|
||||
for (cur = mem_->ram_list_, tmp = 0
|
||||
; cur||tmp ; cur = cur? cur->next_ : tmp) {
|
||||
tmp = 0;
|
||||
if (cur == this) continue;
|
||||
|
||||
bool ok_flag = true;
|
||||
for (unsigned idx = 0 ; idx < awidth() ; idx += 1)
|
||||
ok_flag &= pin_Address(idx).is_linked(cur->pin_Address(idx));
|
||||
|
||||
if (!ok_flag) continue;
|
||||
|
||||
if (pin_InClock().is_linked()
|
||||
&& cur->pin_InClock().is_linked()
|
||||
&& ! pin_InClock().is_linked(cur->pin_InClock()))
|
||||
continue;
|
||||
|
||||
if (pin_OutClock().is_linked()
|
||||
&& cur->pin_OutClock().is_linked()
|
||||
&& ! pin_OutClock().is_linked(cur->pin_OutClock()))
|
||||
continue;
|
||||
|
||||
if (pin_WE().is_linked()
|
||||
&& cur->pin_WE().is_linked()
|
||||
&& ! pin_WE().is_linked(cur->pin_WE()))
|
||||
continue;
|
||||
|
||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
||||
if (!pin_Data(idx).is_linked()) continue;
|
||||
if (! cur->pin_Data(idx).is_linked()) continue;
|
||||
|
||||
ok_flag &= pin_Data(idx).is_linked(cur->pin_Data(idx));
|
||||
}
|
||||
|
||||
if (! ok_flag) continue;
|
||||
|
||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
||||
if (!pin_Q(idx).is_linked()) continue;
|
||||
if (! cur->pin_Q(idx).is_linked()) continue;
|
||||
|
||||
ok_flag &= pin_Q(idx).is_linked(cur->pin_Q(idx));
|
||||
}
|
||||
|
||||
if (! ok_flag) continue;
|
||||
|
||||
// I see no other reason to reject cur, so link up all
|
||||
// my pins and delete it.
|
||||
connect(pin_InClock(), cur->pin_InClock());
|
||||
connect(pin_OutClock(), cur->pin_OutClock());
|
||||
connect(pin_WE(), cur->pin_WE());
|
||||
|
||||
for (unsigned idx = 0 ; idx < awidth() ; idx += 1)
|
||||
connect(pin_Address(idx), cur->pin_Address(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
||||
connect(pin_Data(idx), cur->pin_Data(idx));
|
||||
connect(pin_Q(idx), cur->pin_Q(idx));
|
||||
}
|
||||
|
||||
tmp = cur->next_;
|
||||
delete cur;
|
||||
cur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NetObj::Link& NetRamDq::pin_InClock()
|
||||
{
|
||||
return pin(0);
|
||||
@@ -1249,16 +1470,18 @@ NetAssignNB::~NetAssignNB()
|
||||
}
|
||||
|
||||
|
||||
NetAssignMem_::NetAssignMem_(NetMemory*m, NetExpr*i, NetExpr*r)
|
||||
NetAssignMem_::NetAssignMem_(NetMemory*m, NetNet*i, NetExpr*r)
|
||||
: mem_(m), index_(i), rval_(r)
|
||||
{
|
||||
index_->incr_eref();
|
||||
}
|
||||
|
||||
NetAssignMem_::~NetAssignMem_()
|
||||
{
|
||||
index_->decr_eref();
|
||||
}
|
||||
|
||||
NetAssignMem::NetAssignMem(NetMemory*m, NetExpr*i, NetExpr*r)
|
||||
NetAssignMem::NetAssignMem(NetMemory*m, NetNet*i, NetExpr*r)
|
||||
: NetAssignMem_(m, i, r)
|
||||
{
|
||||
}
|
||||
@@ -1267,7 +1490,7 @@ NetAssignMem::~NetAssignMem()
|
||||
{
|
||||
}
|
||||
|
||||
NetAssignMemNB::NetAssignMemNB(NetMemory*m, NetExpr*i, NetExpr*r)
|
||||
NetAssignMemNB::NetAssignMemNB(NetMemory*m, NetNet*i, NetExpr*r)
|
||||
: NetAssignMem_(m, i, r)
|
||||
{
|
||||
}
|
||||
@@ -1386,14 +1609,34 @@ NetProc* NetCondit::else_clause()
|
||||
}
|
||||
|
||||
NetConst::NetConst(const string&n, verinum::V v)
|
||||
: NetNode(n, 1), value_(v)
|
||||
: NetNode(n, 1)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name("O", 0);
|
||||
value_ = new verinum::V[1];
|
||||
value_[0] = v;
|
||||
}
|
||||
|
||||
NetConst::NetConst(const string&n, const verinum&val)
|
||||
: NetNode(n, val.len())
|
||||
{
|
||||
value_ = new verinum::V[pin_count()];
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::OUTPUT);
|
||||
pin(idx).set_name("O", idx);
|
||||
value_[idx] = val.get(idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetConst::~NetConst()
|
||||
{
|
||||
delete[]value_;
|
||||
}
|
||||
|
||||
verinum::V NetConst::value(unsigned idx) const
|
||||
{
|
||||
assert(idx < pin_count());
|
||||
return value_[idx];
|
||||
}
|
||||
|
||||
NetFuncDef::NetFuncDef(const string&n, const svector<NetNet*>&po)
|
||||
@@ -1675,6 +1918,23 @@ NetEBLogic* NetEBLogic::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
expr_width(l->expr_width() + r->expr_width());
|
||||
}
|
||||
|
||||
NetEBMult::~NetEBMult()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBMult* NetEBMult::dup_expr() const
|
||||
{
|
||||
NetEBMult*result = new NetEBMult(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
@@ -1757,7 +2017,7 @@ NetEMemory::~NetEMemory()
|
||||
}
|
||||
|
||||
NetMemory::NetMemory(const string&n, long w, long s, long e)
|
||||
: name_(n), width_(w), idxh_(s), idxl_(e)
|
||||
: name_(n), width_(w), idxh_(s), idxl_(e), ram_list_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1978,12 +2238,12 @@ const NetExpr* NetRepeat::expr() const
|
||||
}
|
||||
|
||||
NetScope::NetScope(const string&n)
|
||||
: type_(NetScope::MODULE), name_(n)
|
||||
: type_(NetScope::MODULE), name_(n), up_(0)
|
||||
{
|
||||
}
|
||||
|
||||
NetScope::NetScope(const string&p, NetScope::TYPE t)
|
||||
: type_(t), name_(p)
|
||||
NetScope::NetScope(NetScope*up, const string&n, NetScope::TYPE t)
|
||||
: type_(t), name_(n), up_(up)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1998,7 +2258,15 @@ NetScope::TYPE NetScope::type() const
|
||||
|
||||
string NetScope::name() const
|
||||
{
|
||||
return name_;
|
||||
if (up_)
|
||||
return up_->name() + "." + name_;
|
||||
else
|
||||
return name_;
|
||||
}
|
||||
|
||||
const NetScope* NetScope::parent() const
|
||||
{
|
||||
return up_;
|
||||
}
|
||||
|
||||
NetTaskDef::NetTaskDef(const string&n, const svector<NetNet*>&po)
|
||||
@@ -2313,9 +2581,12 @@ NetScope* Design::make_scope(const string&path,
|
||||
NetScope::TYPE t,
|
||||
const string&name)
|
||||
{
|
||||
string npath = path + "." + name;
|
||||
NetScope*scope = new NetScope(npath, t);
|
||||
scopes_[npath] = scope;
|
||||
NetScope*up = find_scope(path);
|
||||
assert(up);
|
||||
|
||||
NetScope*scope = new NetScope(up, name, t);
|
||||
scopes_[scope->name()] = scope;
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
@@ -2641,6 +2912,30 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
||||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.105 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.104 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.103 2000/01/10 01:35:24 steve
|
||||
* Elaborate parameters afer binding of overrides.
|
||||
*
|
||||
* 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).
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __netlist_H
|
||||
#define __netlist_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: netlist.h,v 1.97 1999/12/01 06:06:16 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netlist.h,v 1.110 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -321,12 +321,14 @@ class NetAddSub : public NetNode {
|
||||
NetObj::Link& pin_DataB(unsigned idx);
|
||||
NetObj::Link& pin_Result(unsigned idx);
|
||||
|
||||
const NetObj::Link& pin_Cout() const;
|
||||
const NetObj::Link& pin_DataA(unsigned idx) const;
|
||||
const NetObj::Link& pin_DataB(unsigned idx) const;
|
||||
const NetObj::Link& pin_Result(unsigned idx) const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -480,8 +482,61 @@ class NetMemory {
|
||||
long idxl_;
|
||||
|
||||
map<string,string> attributes_;
|
||||
|
||||
friend class NetRamDq;
|
||||
NetRamDq* ram_list_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class implements the LPM_MULT component as described in the
|
||||
* EDIF LPM Version 2 1 0 standard. It is used as a structural
|
||||
* implementation of the * operator. The device has inputs DataA and
|
||||
* DataB that can have independent widths, as can the result. If the
|
||||
* result is smaller then the widths of a and b together, then the
|
||||
* device drops the least significant bits of the product.
|
||||
*/
|
||||
class NetMult : public NetNode {
|
||||
|
||||
public:
|
||||
NetMult(const string&n, unsigned width, unsigned wa, unsigned wb,
|
||||
unsigned width_s =0);
|
||||
~NetMult();
|
||||
|
||||
// Get the width of the device bussed inputs. There are these
|
||||
// parameterized widths:
|
||||
unsigned width_r() const; // Result
|
||||
unsigned width_a() const; // DataA
|
||||
unsigned width_b() const; // DataB
|
||||
unsigned width_s() const; // Sum (my be 0)
|
||||
|
||||
NetObj::Link& pin_Aclr();
|
||||
NetObj::Link& pin_Clock();
|
||||
|
||||
NetObj::Link& pin_DataA(unsigned idx);
|
||||
NetObj::Link& pin_DataB(unsigned idx);
|
||||
NetObj::Link& pin_Result(unsigned idx);
|
||||
NetObj::Link& pin_Sum(unsigned idx);
|
||||
|
||||
const NetObj::Link& pin_Aclr() const;
|
||||
const NetObj::Link& pin_Clock() const;
|
||||
|
||||
const NetObj::Link& pin_DataA(unsigned idx) const;
|
||||
const NetObj::Link& pin_DataB(unsigned idx) const;
|
||||
const NetObj::Link& pin_Result(unsigned idx) const;
|
||||
const NetObj::Link& pin_Sum(unsigned idx) const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
unsigned width_r_;
|
||||
unsigned width_a_;
|
||||
unsigned width_b_;
|
||||
unsigned width_s_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This class represents an LPM_MUX device. This device has some
|
||||
* number of Result points (the width of the device) and some number
|
||||
@@ -561,8 +616,16 @@ class NetRamDq : public NetNode {
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
|
||||
// Use this method to absorb other NetRamDq objects that are
|
||||
// connected to the same memory, and have compatible pin
|
||||
// connections.
|
||||
void absorb_partners();
|
||||
|
||||
// Use this method to count the partners (including myself)
|
||||
// that are ports to the attached memory.
|
||||
unsigned count_partners() const;
|
||||
|
||||
private:
|
||||
friend class NetMemory;
|
||||
NetMemory*mem_;
|
||||
NetRamDq*next_;
|
||||
unsigned awidth_;
|
||||
@@ -695,20 +758,29 @@ class NetCaseCmp : public NetNode {
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This class represents instances of the LPM_CONSTANT device. The
|
||||
* node has only outputs and a constant value. The width is available
|
||||
* by getting the pin_count(), and the value bits are available one at
|
||||
* a time. There is no meaning to the aggregation of bits to form a
|
||||
* wide NetConst object, although some targets may have an easier time
|
||||
* detecting interesting constructs if they are combined.
|
||||
*/
|
||||
class NetConst : public NetNode {
|
||||
|
||||
public:
|
||||
explicit NetConst(const string&n, verinum::V v);
|
||||
explicit NetConst(const string&n, const verinum&val);
|
||||
~NetConst();
|
||||
|
||||
verinum::V value() const { return value_; }
|
||||
verinum::V value(unsigned idx) const;
|
||||
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
virtual void functor_node(Design*, functor_t*);
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
verinum::V value_;
|
||||
verinum::V*value_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -727,6 +799,7 @@ class NetLogic : public NetNode {
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
virtual void functor_node(Design*, functor_t*);
|
||||
|
||||
private:
|
||||
const TYPE type_;
|
||||
@@ -957,25 +1030,30 @@ class NetAssignNB : public NetAssign_ {
|
||||
class NetAssignMem_ : public NetProc {
|
||||
|
||||
public:
|
||||
explicit NetAssignMem_(NetMemory*, NetExpr*idx, NetExpr*rv);
|
||||
explicit NetAssignMem_(NetMemory*, NetNet*idx, NetExpr*rv);
|
||||
~NetAssignMem_();
|
||||
|
||||
NetMemory*memory() { return mem_; }
|
||||
NetNet*index() { return index_; }
|
||||
NetExpr*rval() { return rval_; }
|
||||
|
||||
const NetMemory*memory()const { return mem_; }
|
||||
const NetExpr*index()const { return index_; }
|
||||
const NetExpr*rval()const { return rval_; }
|
||||
const NetNet*index()const { return index_; }
|
||||
const NetExpr*rval()const { return rval_; }
|
||||
|
||||
private:
|
||||
NetMemory*mem_;
|
||||
NetExpr* index_;
|
||||
NetNet * index_;
|
||||
NetExpr* rval_;
|
||||
};
|
||||
|
||||
class NetAssignMem : public NetAssignMem_ {
|
||||
|
||||
public:
|
||||
explicit NetAssignMem(NetMemory*, NetExpr*idx, NetExpr*rv);
|
||||
explicit NetAssignMem(NetMemory*, NetNet*idx, NetExpr*rv);
|
||||
~NetAssignMem();
|
||||
|
||||
virtual int match_proc(struct proc_match_t*);
|
||||
virtual bool emit_proc(ostream&, struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
@@ -985,7 +1063,7 @@ class NetAssignMem : public NetAssignMem_ {
|
||||
class NetAssignMemNB : public NetAssignMem_ {
|
||||
|
||||
public:
|
||||
explicit NetAssignMemNB(NetMemory*, NetExpr*idx, NetExpr*rv);
|
||||
explicit NetAssignMemNB(NetMemory*, NetNet*idx, NetExpr*rv);
|
||||
~NetAssignMemNB();
|
||||
|
||||
virtual bool emit_proc(ostream&, struct target_t*) const;
|
||||
@@ -994,7 +1072,7 @@ class NetAssignMemNB : public NetAssignMem_ {
|
||||
private:
|
||||
};
|
||||
|
||||
/* A block is stuff line begin-end blocks, that contain and ordered
|
||||
/* A block is stuff like begin-end blocks, that contain an ordered
|
||||
list of NetProc statements.
|
||||
|
||||
NOTE: The emit method calls the target->proc_block function but
|
||||
@@ -1014,6 +1092,7 @@ class NetBlock : public NetProc {
|
||||
|
||||
void emit_recurse(ostream&, struct target_t*) const;
|
||||
virtual bool emit_proc(ostream&, struct target_t*) const;
|
||||
virtual int match_proc(struct proc_match_t*);
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -1555,6 +1634,23 @@ class NetEBLogic : public NetEBinary {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Support the binary multiplication (*) operator.
|
||||
*/
|
||||
class NetEBMult : public NetEBinary {
|
||||
|
||||
public:
|
||||
NetEBMult(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBMult();
|
||||
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEBMult* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The binary logical operators are those that return boolean
|
||||
* results. The supported operators are:
|
||||
@@ -1601,6 +1697,7 @@ class NetEConcat : public NetExpr {
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEConcat* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
@@ -1787,12 +1884,14 @@ class NetEIdent : public NetExpr {
|
||||
};
|
||||
|
||||
/*
|
||||
* A reference to a memory is represented by this expression.
|
||||
* A reference to a memory is represented by this expression. If the
|
||||
* index is not supplied, then the node is only valid in certain
|
||||
* specific contexts.
|
||||
*/
|
||||
class NetEMemory : public NetExpr {
|
||||
|
||||
public:
|
||||
NetEMemory(NetMemory*mem, NetExpr*idx);
|
||||
NetEMemory(NetMemory*mem, NetExpr*idx =0);
|
||||
virtual ~NetEMemory();
|
||||
|
||||
const string& name () const { return mem_->name(); }
|
||||
@@ -1883,17 +1982,19 @@ class NetScope {
|
||||
public:
|
||||
enum TYPE { MODULE, BEGIN_END, FORK_JOIN };
|
||||
NetScope(const string&root);
|
||||
NetScope(const string&path, TYPE t);
|
||||
NetScope(NetScope*up, const string&name, TYPE t);
|
||||
~NetScope();
|
||||
|
||||
TYPE type() const;
|
||||
string name() const;
|
||||
const NetScope* parent() const;
|
||||
|
||||
void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
TYPE type_;
|
||||
string name_;
|
||||
NetScope*up_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2051,6 +2152,45 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.110 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.109 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.108 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.107 2000/01/10 01:35:24 steve
|
||||
* Elaborate parameters afer binding of overrides.
|
||||
*
|
||||
* Revision 1.106 2000/01/01 06:18:00 steve
|
||||
* Handle synthesis of concatenation.
|
||||
*
|
||||
* Revision 1.105 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.104 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.103 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.102 1999/12/16 02:42:15 steve
|
||||
* Simulate carry output on adders.
|
||||
*
|
||||
* Revision 1.101 1999/12/12 06:03:14 steve
|
||||
* Allow memories without indices in expressions.
|
||||
*
|
||||
* Revision 1.100 1999/12/09 06:00:00 steve
|
||||
* Fix const/non-const errors.
|
||||
*
|
||||
* 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/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __netmisc_H
|
||||
#define __netmisc_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: netmisc.h,v 1.1 1999/09/29 00:42:51 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netmisc.h,v 1.3 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -31,10 +31,16 @@
|
||||
* enough.
|
||||
*/
|
||||
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid);
|
||||
|
||||
extern NetNet*pad_to_width(Design*des, const string&p, NetNet*n, unsigned w);
|
||||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.3 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.1 1999/09/29 00:42:51 steve
|
||||
* Allow expanding of additive operators.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: nobufz.cc,v 1.1 1998/12/02 04:37:13 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: nobufz.cc,v 1.2 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/* NOBUFZ Function
|
||||
@@ -61,6 +61,9 @@ void nobufz(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: nobufz.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1998/12/02 04:37:13 steve
|
||||
* Add the nobufz function to eliminate bufz objects,
|
||||
* Object links are marked with direction,
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999 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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: nodangle.cc,v 1.2 1999/11/28 23:42:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: nodangle.cc,v 1.3 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -73,6 +73,9 @@ void nodangle(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: nodangle.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
+34
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: pad_to_width.cc,v 1.1 1999/09/29 00:42:51 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pad_to_width.cc,v 1.4 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -34,7 +34,9 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
|
||||
if (wid > expr->expr_width()) {
|
||||
verinum pad(verinum::V0, wid - expr->expr_width());
|
||||
NetEConst*co = new NetEConst(pad);
|
||||
co->set_line(*expr);
|
||||
NetEConcat*cc = new NetEConcat(2);
|
||||
cc->set_line(*expr);
|
||||
cc->set(0, co);
|
||||
cc->set(1, expr);
|
||||
cc->set_width(wid);
|
||||
@@ -43,9 +45,38 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
|
||||
return expr;
|
||||
}
|
||||
|
||||
NetNet*pad_to_width(Design*des, const string&path, NetNet*net, unsigned wid)
|
||||
{
|
||||
if (net->pin_count() >= wid)
|
||||
return net;
|
||||
|
||||
verinum pad(verinum::V0, wid - net->pin_count());
|
||||
NetConst*con = new NetConst(des->local_symbol(path), pad);
|
||||
des->add_node(con);
|
||||
|
||||
NetNet*tmp = new NetNet(0, des->local_symbol(path), NetNet::WIRE, wid);
|
||||
tmp->local_flag(true);
|
||||
des->add_signal(tmp);
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
connect(tmp->pin(idx), net->pin(idx));
|
||||
for (unsigned idx = net->pin_count() ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), con->pin(idx-net->pin_count()));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: pad_to_width.cc,v $
|
||||
* Revision 1.4 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.2 2000/01/01 06:17:25 steve
|
||||
* Propogate line number information when expanding expressions.
|
||||
*
|
||||
* Revision 1.1 1999/09/29 00:42:51 steve
|
||||
* Allow expanding of additive operators.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: parse.y,v 1.76 1999/11/15 04:43:52 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse.y,v 1.83 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
@@ -45,6 +45,7 @@ extern void lex_end_table();
|
||||
|
||||
portname_t*portname;
|
||||
svector<portname_t*>*portnames;
|
||||
struct parmvalue_t*parmvalue;
|
||||
|
||||
PExpr*expr;
|
||||
svector<PExpr*>*exprs;
|
||||
@@ -74,7 +75,7 @@ extern void lex_end_table();
|
||||
%token <number> NUMBER
|
||||
%token <realtime> REALTIME
|
||||
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_SG
|
||||
%token K_LOR K_LAND K_NAND K_NOR K_NXOR
|
||||
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
|
||||
%token K_always K_and K_assign K_begin K_buf K_bufif0 K_bufif1 K_case
|
||||
%token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable
|
||||
%token K_edge K_else K_end K_endcase K_endfunction K_endmodule
|
||||
@@ -115,8 +116,8 @@ extern void lex_end_table();
|
||||
%type <wires> task_item task_item_list task_item_list_opt
|
||||
%type <wires> function_item function_item_list
|
||||
|
||||
%type <portname> port_name
|
||||
%type <portnames> port_name_list
|
||||
%type <portname> port_name parameter_value_byname
|
||||
%type <portnames> port_name_list parameter_value_byname_list
|
||||
|
||||
%type <citem> case_item
|
||||
%type <citems> case_items
|
||||
@@ -126,8 +127,8 @@ extern void lex_end_table();
|
||||
|
||||
%type <expr> expression expr_primary
|
||||
%type <expr> lavalue lpvalue
|
||||
%type <expr> delay_value
|
||||
%type <exprs> delay delay_opt delay_value_list
|
||||
%type <expr> delay_value delay_value_simple
|
||||
%type <exprs> delay1 delay3 delay3_opt
|
||||
%type <exprs> expression_list
|
||||
%type <exprs> assign assign_list
|
||||
|
||||
@@ -135,6 +136,7 @@ extern void lex_end_table();
|
||||
%type <nettype> net_type
|
||||
%type <gatetype> gatetype
|
||||
%type <porttype> port_type
|
||||
%type <parmvalue> parameter_value_opt
|
||||
|
||||
%type <task> task_body
|
||||
%type <function> func_body
|
||||
@@ -275,23 +277,67 @@ defparam_assign_list
|
||||
| defparam_assign_list ',' defparam_assign
|
||||
;
|
||||
|
||||
delay
|
||||
: '#' delay_value
|
||||
delay1
|
||||
: '#' delay_value_simple
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
||||
(*tmp)[0] = $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '#' '(' delay_value_list ')'
|
||||
{ $$ = $3;
|
||||
| '#' '(' delay_value ')'
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
||||
(*tmp)[0] = $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
delay_opt
|
||||
: delay { $$ = $1; }
|
||||
| { $$ = 0; }
|
||||
delay3
|
||||
: '#' delay_value_simple
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
||||
(*tmp)[0] = $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '#' '(' delay_value ')'
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
||||
(*tmp)[0] = $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '#' '(' delay_value ',' delay_value ')'
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(2);
|
||||
(*tmp)[0] = $3;
|
||||
(*tmp)[1] = $5;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '#' '(' delay_value ',' delay_value ',' delay_value ')'
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(3);
|
||||
(*tmp)[0] = $3;
|
||||
(*tmp)[1] = $5;
|
||||
(*tmp)[1] = $7;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
delay3_opt
|
||||
: delay3 { $$ = $1; }
|
||||
| { $$ = 0; }
|
||||
;
|
||||
|
||||
delay_value
|
||||
: expression
|
||||
{ PExpr*tmp = $1;
|
||||
if (! pform_expression_is_constant(tmp))
|
||||
yyerror(@1, "error: delay expression must "
|
||||
"be constant.");
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression ':' expression ':' expression
|
||||
{ yyerror(@1, "sorry: (min:typ:max) not supported.");
|
||||
$$ = $3;
|
||||
delete $1;
|
||||
delete $5;
|
||||
}
|
||||
;
|
||||
|
||||
delay_value_simple
|
||||
: NUMBER
|
||||
{ verinum*tmp = $1;
|
||||
if (tmp == 0) {
|
||||
@@ -312,19 +358,6 @@ delay_value
|
||||
}
|
||||
;
|
||||
|
||||
delay_value_list
|
||||
: expression
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
||||
(*tmp)[0] = $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| delay_value_list ',' expression
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
description
|
||||
: module
|
||||
| udp_primitive
|
||||
@@ -694,12 +727,6 @@ expr_primary
|
||||
}
|
||||
| '(' expression ')'
|
||||
{ $$ = $2; }
|
||||
| '(' expression ':' expression ':' expression ')'
|
||||
{ yyerror(@2, "sorry: (min:typ:max) not supported.");
|
||||
$$ = $4;
|
||||
delete $2;
|
||||
delete $6;
|
||||
}
|
||||
| '{' expression_list '}'
|
||||
{ PEConcat*tmp = new PEConcat(*$2);
|
||||
tmp->set_file(@2.text);
|
||||
@@ -1051,7 +1078,7 @@ module_item
|
||||
}
|
||||
delete $3;
|
||||
}
|
||||
| K_trireg charge_strength_opt range_opt delay_opt list_of_variables ';'
|
||||
| K_trireg charge_strength_opt range_opt delay3_opt list_of_variables ';'
|
||||
{ yyerror(@1, "sorry: trireg nets not supported.");
|
||||
delete $3;
|
||||
}
|
||||
@@ -1070,14 +1097,14 @@ module_item
|
||||
delete $2;
|
||||
}
|
||||
| K_parameter parameter_assign_list ';'
|
||||
| gatetype delay_opt gate_instance_list ';'
|
||||
| gatetype delay3_opt gate_instance_list ';'
|
||||
{ pform_makegates($1, $2, $3);
|
||||
}
|
||||
| IDENTIFIER delay_opt gate_instance_list ';'
|
||||
| IDENTIFIER parameter_value_opt gate_instance_list ';'
|
||||
{ pform_make_modgates($1, $2, $3);
|
||||
delete $1;
|
||||
}
|
||||
| K_assign drive_strength_opt delay_opt assign_list ';'
|
||||
| K_assign drive_strength_opt delay3_opt assign_list ';'
|
||||
{ pform_make_pgassign_list($4, $3, @1.text, @1.first_line); }
|
||||
| K_assign error '=' expression ';'
|
||||
| K_always statement
|
||||
@@ -1141,7 +1168,7 @@ net_decl_assign
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = $1;
|
||||
}
|
||||
| delay IDENTIFIER '=' expression
|
||||
| delay1 IDENTIFIER '=' expression
|
||||
{ PEIdent*id = new PEIdent($2);
|
||||
PGAssign*tmp = pform_make_pgassign(id, $4, $1);
|
||||
tmp->set_file(@2.text);
|
||||
@@ -1202,7 +1229,86 @@ parameter_assign_list
|
||||
| parameter_assign_list ',' parameter_assign
|
||||
;
|
||||
|
||||
/* The port (of a module) is a fairle complex item. Each port is
|
||||
|
||||
/* The parameters of a module instance can be overridden by writing
|
||||
a list of expressions in a syntax much line a delay list. (The
|
||||
difference being the list can have any length.) The pform that
|
||||
attaches the expression list to the module checks that the
|
||||
expressions are constant.
|
||||
|
||||
Although the BNF in IEEE1364-1995 implies that parameter value
|
||||
lists must be in parentheses, in practice most compilers will
|
||||
accept simple expressions outside of parentheses if there is only
|
||||
one value, so I'll accept simple numbers here.
|
||||
|
||||
The parameter value by name syntax is OVI enhancement BTF-B06 as
|
||||
approved by WG1364 on 6/28/1998. */
|
||||
|
||||
parameter_value_opt
|
||||
: '#' '(' expression_list ')'
|
||||
{ struct parmvalue_t*tmp = new struct parmvalue_t;
|
||||
tmp->by_order = $3;
|
||||
tmp->by_name = 0;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '#' '(' parameter_value_byname_list ')'
|
||||
{ struct parmvalue_t*tmp = new struct parmvalue_t;
|
||||
tmp->by_order = 0;
|
||||
tmp->by_name = $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '#' NUMBER
|
||||
{ assert($2);
|
||||
PENumber*tmp = new PENumber($2);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
|
||||
struct parmvalue_t*lst = new struct parmvalue_t;
|
||||
lst->by_order = new svector<PExpr*>(1);
|
||||
(*lst->by_order)[0] = tmp;
|
||||
lst->by_name = 0;
|
||||
$$ = lst;
|
||||
}
|
||||
| '#' error
|
||||
{ yyerror(@1, "error: syntax error in parameter value "
|
||||
"assignment list.");
|
||||
$$ = 0;
|
||||
}
|
||||
|
|
||||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
parameter_value_byname
|
||||
: PORTNAME '(' expression ')'
|
||||
{ portname_t*tmp = new portname_t;
|
||||
tmp->name = $1;
|
||||
tmp->parm = $3;
|
||||
free($1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| PORTNAME '(' ')'
|
||||
{ portname_t*tmp = new portname_t;
|
||||
tmp->name = $1;
|
||||
tmp->parm = 0;
|
||||
free($1);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
parameter_value_byname_list
|
||||
: parameter_value_byname
|
||||
{ svector<portname_t*>*tmp = new svector<portname_t*>(1);
|
||||
(*tmp)[0] = $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| parameter_value_byname_list ',' parameter_value_byname
|
||||
{ svector<portname_t*>*tmp = new svector<portname_t*>(*$1,$3);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
/* The port (of a module) is a fairly complex item. Each port is
|
||||
handled as a Module::port_t object. A simple port reference has a
|
||||
name and a PWire object, but more complex constructs are possible
|
||||
where the name can be attached to a list of PWire objects.
|
||||
@@ -1390,8 +1496,10 @@ register_variable
|
||||
}
|
||||
| IDENTIFIER '=' expression
|
||||
{ pform_makewire(@1, $1, NetNet::REG);
|
||||
yyerror(@2, "error: net declaration assignment to reg/integer not allowed.");
|
||||
delete $3;
|
||||
if (! pform_expression_is_constant($3))
|
||||
yyerror(@3, "error: register declaration assignment"
|
||||
" value must be a constant expression.");
|
||||
pform_make_reginit(@1, $1, $3);
|
||||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER '[' expression ':' expression ']'
|
||||
@@ -1502,6 +1610,10 @@ statement
|
||||
{ yyerror(@1, "sorry: procedural force assign not supported.");
|
||||
$$ = 0;
|
||||
}
|
||||
| K_TRIGGER IDENTIFIER ';'
|
||||
{ yyerror(@1, "sorry: event trigger not supported.");
|
||||
$$ = 0;
|
||||
}
|
||||
| K_forever statement
|
||||
{ PForever*tmp = new PForever($2);
|
||||
tmp->set_file(@1.text);
|
||||
@@ -1622,10 +1734,9 @@ statement
|
||||
{ $$ = 0;
|
||||
yyerror(@3, "error: Error in while loop condition.");
|
||||
}
|
||||
| delay statement_opt
|
||||
| delay1 statement_opt
|
||||
{ PExpr*del = (*$1)[0];
|
||||
if ($1->count() != 1)
|
||||
yyerror(@1, "sorry: delay lists not supported here.");
|
||||
assert($1->count() == 1);
|
||||
PDelayStatement*tmp = new PDelayStatement(del, $2);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
@@ -1653,19 +1764,17 @@ statement
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| lpvalue '=' delay expression ';'
|
||||
{ PExpr*del = (*$3)[0];
|
||||
if ($3->count() != 1)
|
||||
yyerror(@1, "sorry: Delay lists not supported here.");
|
||||
| lpvalue '=' delay1 expression ';'
|
||||
{ assert($3->count() == 1);
|
||||
PExpr*del = (*$3)[0];
|
||||
PAssign*tmp = new PAssign($1,del,$4);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| lpvalue K_LE delay expression ';'
|
||||
{ PExpr*del = (*$3)[0];
|
||||
if ($3->count() != 1)
|
||||
yyerror(@1, "sorry: Delay lists not supported here.");
|
||||
| lpvalue K_LE delay1 expression ';'
|
||||
{ assert($3->count() == 1);
|
||||
PExpr*del = (*$3)[0];
|
||||
PAssignNB*tmp = new PAssignNB($1,del,$4);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
@@ -1677,6 +1786,14 @@ statement
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| lpvalue '=' K_repeat '(' expression ')' event_control expression ';'
|
||||
{ PAssign*tmp = new PAssign($1,$7,$8);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
yyerror(@3, "sorry: repeat event control not supported.");
|
||||
delete $5;
|
||||
$$ = tmp;
|
||||
}
|
||||
| lpvalue K_LE event_control expression ';'
|
||||
{ yyerror(@1, "sorry: Event controls not supported here.");
|
||||
PAssignNB*tmp = new PAssignNB($1,$4);
|
||||
@@ -1684,6 +1801,14 @@ statement
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| lpvalue K_LE K_repeat '(' expression ')' event_control expression ';'
|
||||
{ yyerror(@1, "sorry: Event controls not supported here.");
|
||||
delete $5;
|
||||
PAssignNB*tmp = new PAssignNB($1,$8);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_wait '(' expression ')' statement_opt
|
||||
{ PEventStatement*tmp;
|
||||
PEEvent*etmp = new PEEvent(NetNEvent::POSITIVE, $3);
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-1999 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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: parse_misc.cc,v 1.3 1999/09/29 21:15:31 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse_misc.cc,v 1.4 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
@@ -58,6 +58,9 @@ int VLwrap()
|
||||
|
||||
/*
|
||||
* $Log: parse_misc.cc,v $
|
||||
* Revision 1.4 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/09/29 21:15:31 steve
|
||||
* Standardize formatting of warning messages.
|
||||
*
|
||||
|
||||
+6
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef __parse_misc_H
|
||||
#define __parse_misc_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: parse_misc.h,v 1.3 1999/07/10 01:03:18 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse_misc.h,v 1.4 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -53,6 +53,9 @@ extern unsigned error_count, warn_count;
|
||||
|
||||
/*
|
||||
* $Log: parse_misc.h,v $
|
||||
* Revision 1.4 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/07/10 01:03:18 steve
|
||||
* remove string from lexical phase.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: pform.cc,v 1.47 1999/11/23 01:04:57 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pform.cc,v 1.54 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compiler.h"
|
||||
@@ -303,12 +303,15 @@ void pform_makegates(PGBuiltin::Type type,
|
||||
|
||||
/*
|
||||
* A module is different from a gate in that there are different
|
||||
* constraints, and sometimes different syntax.
|
||||
* constraints, and sometimes different syntax. The X_modgate
|
||||
* functions handle the instantaions of modules (and UDP objects) by
|
||||
* making PGModule objects.
|
||||
*/
|
||||
static void pform_make_modgate(const string&type,
|
||||
const string&name,
|
||||
svector<PExpr*>*overrides,
|
||||
struct parmvalue_t*overrides,
|
||||
svector<PExpr*>*wires,
|
||||
PExpr*msb, PExpr*lsb,
|
||||
const string&fn, unsigned ln)
|
||||
{
|
||||
if (name == "") {
|
||||
@@ -318,16 +321,35 @@ static void pform_make_modgate(const string&type,
|
||||
return;
|
||||
}
|
||||
|
||||
PGate*cur = new PGModule(type, name, overrides, wires);
|
||||
PGModule*cur = new PGModule(type, name, wires);
|
||||
cur->set_file(fn);
|
||||
cur->set_lineno(ln);
|
||||
cur->set_range(msb,lsb);
|
||||
|
||||
if (overrides && overrides->by_name) {
|
||||
unsigned cnt = overrides->by_name->count();
|
||||
named<PExpr*>*byname = new named<PExpr*>[cnt];
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
portname_t*curp = (*overrides->by_name)[idx];
|
||||
byname[idx].name = curp->name;
|
||||
byname[idx].parm = curp->parm;
|
||||
}
|
||||
|
||||
cur->set_parameters(byname, cnt);
|
||||
|
||||
} else if (overrides && overrides->by_order) {
|
||||
cur->set_parameters(overrides->by_order);
|
||||
}
|
||||
|
||||
pform_cur_module->add_gate(cur);
|
||||
}
|
||||
|
||||
static void pform_make_modgate(const string&type,
|
||||
const string&name,
|
||||
svector<PExpr*>*overrides,
|
||||
struct parmvalue_t*overrides,
|
||||
svector<portname_t*>*bind,
|
||||
PExpr*msb, PExpr*lsb,
|
||||
const string&fn, unsigned ln)
|
||||
{
|
||||
if (name == "") {
|
||||
@@ -338,37 +360,70 @@ static void pform_make_modgate(const string&type,
|
||||
}
|
||||
|
||||
unsigned npins = bind->count();
|
||||
PGModule::bind_t*pins = new PGModule::bind_t[npins];
|
||||
named<PExpr*>*pins = new named<PExpr*>[npins];
|
||||
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
|
||||
portname_t*curp = (*bind)[idx];
|
||||
pins[idx].name = curp->name;
|
||||
pins[idx].parm = curp->parm;
|
||||
}
|
||||
|
||||
PGate*cur = new PGModule(type, name, overrides, pins, npins);
|
||||
PGModule*cur = new PGModule(type, name, pins, npins);
|
||||
cur->set_file(fn);
|
||||
cur->set_lineno(ln);
|
||||
cur->set_range(msb,lsb);
|
||||
|
||||
if (overrides && overrides->by_name) {
|
||||
unsigned cnt = overrides->by_name->count();
|
||||
named<PExpr*>*byname = new named<PExpr*>[cnt];
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
portname_t*curp = (*overrides->by_name)[idx];
|
||||
byname[idx].name = curp->name;
|
||||
byname[idx].parm = curp->parm;
|
||||
}
|
||||
|
||||
cur->set_parameters(byname, cnt);
|
||||
|
||||
} else if (overrides && overrides->by_order) {
|
||||
|
||||
cur->set_parameters(overrides->by_order);
|
||||
}
|
||||
|
||||
pform_cur_module->add_gate(cur);
|
||||
}
|
||||
|
||||
void pform_make_modgates(const string&type,
|
||||
svector<PExpr*>*overrides,
|
||||
struct parmvalue_t*overrides,
|
||||
svector<lgate>*gates)
|
||||
{
|
||||
if (overrides && overrides->by_order)
|
||||
for (unsigned idx = 0 ; idx < overrides->by_order->count() ; idx += 1)
|
||||
if (! pform_expression_is_constant((*overrides->by_order)[idx])) {
|
||||
VLerror("error: Parameter override expression"
|
||||
" must be constant.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < gates->count() ; idx += 1) {
|
||||
lgate cur = (*gates)[idx];
|
||||
|
||||
if (cur.parms_by_name) {
|
||||
pform_make_modgate(type, cur.name, overrides, cur.parms_by_name,
|
||||
pform_make_modgate(type, cur.name, overrides,
|
||||
cur.parms_by_name,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.file, cur.lineno);
|
||||
|
||||
} else if (cur.parms) {
|
||||
pform_make_modgate(type, cur.name, overrides, cur.parms, cur.file,
|
||||
cur.lineno);
|
||||
pform_make_modgate(type, cur.name, overrides,
|
||||
cur.parms,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.file, cur.lineno);
|
||||
} else {
|
||||
svector<PExpr*>*wires = new svector<PExpr*>(0);
|
||||
pform_make_modgate(type, cur.name, overrides, wires, cur.file,
|
||||
cur.lineno);
|
||||
pform_make_modgate(type, cur.name, overrides,
|
||||
wires,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.file, cur.lineno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,6 +462,46 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this function makes the initial assignment to a register as given
|
||||
* in the source. It handles the case where a reg variable is assigned
|
||||
* where it it declared:
|
||||
*
|
||||
* reg foo = <expr>;
|
||||
*
|
||||
* This is equivilent to the combination of statements:
|
||||
*
|
||||
* reg foo;
|
||||
* initital foo = <expr>;
|
||||
*
|
||||
* and that is how it is parsed. This syntax is not part of the
|
||||
* IEEE1364-1994 standard, but is approved by OVI as enhancement
|
||||
* BTF-B14.
|
||||
*/
|
||||
void pform_make_reginit(const struct vlltype&li,
|
||||
const string&name, PExpr*expr)
|
||||
{
|
||||
const string sname = scoped_name(name);
|
||||
PWire*cur = pform_cur_module->get_wire(sname);
|
||||
if (cur == 0) {
|
||||
VLerror(li, "internal error: reginit to non-register?");
|
||||
delete expr;
|
||||
return;
|
||||
}
|
||||
|
||||
PEIdent*lval = new PEIdent(sname);
|
||||
lval->set_file(li.text);
|
||||
lval->set_lineno(li.first_line);
|
||||
PAssign*ass = new PAssign(lval, expr);
|
||||
ass->set_file(li.text);
|
||||
ass->set_lineno(li.first_line);
|
||||
PProcess*top = new PProcess(PProcess::PR_INITIAL, ass);
|
||||
top->set_file(li.text);
|
||||
top->set_lineno(li.first_line);
|
||||
|
||||
pform_cur_module->add_behavior(top);
|
||||
}
|
||||
|
||||
void pform_makewire(const vlltype&li, const string&nm,
|
||||
NetNet::Type type)
|
||||
{
|
||||
@@ -416,7 +511,7 @@ void pform_makewire(const vlltype&li, const string&nm,
|
||||
if (cur->get_wire_type() != NetNet::IMPLICIT) {
|
||||
strstream msg;
|
||||
msg << name << " previously defined at " <<
|
||||
cur->get_line() << ".";
|
||||
cur->get_line() << "." << ends;
|
||||
VLerror(msg.str());
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
@@ -555,8 +650,16 @@ void pform_set_function(const string&name, svector<PExpr*>*ra, PFunction *func)
|
||||
void pform_set_attrib(const string&name, const string&key, const string&value)
|
||||
{
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
assert(cur);
|
||||
cur->attributes[key] = value;
|
||||
if (PWire*cur = pform_cur_module->get_wire(name)) {
|
||||
cur->attributes[key] = value;
|
||||
|
||||
} else if (PGate*cur = pform_cur_module->get_gate(name)) {
|
||||
cur->attributes[key] = value;
|
||||
|
||||
} else {
|
||||
VLerror("Unable to match name for setting attribute.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -717,6 +820,27 @@ int pform_parse(const char*path, map<string,Module*>&modules,
|
||||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.54 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.53 2000/02/18 05:15:03 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.52 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.51 2000/01/02 01:59:28 steve
|
||||
* Forgot to handle no overrides at all.
|
||||
*
|
||||
* Revision 1.50 2000/01/01 23:47:58 steve
|
||||
* Fix module parameter override syntax.
|
||||
*
|
||||
* Revision 1.49 1999/12/30 19:06:14 steve
|
||||
* Support reg initial assignment syntax.
|
||||
*
|
||||
* Revision 1.48 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.47 1999/11/23 01:04:57 steve
|
||||
* A file name of - means standard input.
|
||||
*
|
||||
@@ -751,155 +875,5 @@ int pform_parse(const char*path, map<string,Module*>&modules,
|
||||
* Revision 1.37 1999/08/03 04:14:49 steve
|
||||
* Parse into pform arbitrarily complex module
|
||||
* port declarations.
|
||||
*
|
||||
* Revision 1.36 1999/08/01 16:34:50 steve
|
||||
* Parse and elaborate rise/fall/decay times
|
||||
* for gates, and handle the rules for partial
|
||||
* lists of times.
|
||||
*
|
||||
* Revision 1.35 1999/07/31 19:15:21 steve
|
||||
* misspelled comment.
|
||||
*
|
||||
* Revision 1.34 1999/07/31 19:14:47 steve
|
||||
* Add functions up to elaboration (Ed Carter)
|
||||
*
|
||||
* Revision 1.33 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.32 1999/07/10 01:03:18 steve
|
||||
* remove string from lexical phase.
|
||||
*
|
||||
* Revision 1.31 1999/07/03 02:12:52 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
* Revision 1.30 1999/06/24 04:24:18 steve
|
||||
* Handle expression widths for EEE and NEE operators,
|
||||
* add named blocks and scope handling,
|
||||
* add registers declared in named blocks.
|
||||
*
|
||||
* Revision 1.29 1999/06/21 01:02:16 steve
|
||||
* Fix merging of UDP port type in decls.
|
||||
*
|
||||
* Revision 1.28 1999/06/17 05:34:42 steve
|
||||
* Clean up interface of the PWire class,
|
||||
* Properly match wire ranges.
|
||||
*
|
||||
* Revision 1.27 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
* Revision 1.26 1999/06/13 23:51:16 steve
|
||||
* l-value part select for procedural assignments.
|
||||
*
|
||||
* Revision 1.25 1999/06/12 20:35:27 steve
|
||||
* parse more verilog.
|
||||
*
|
||||
* Revision 1.24 1999/06/12 03:42:17 steve
|
||||
* Assert state of bit range expressions.
|
||||
*
|
||||
* Revision 1.23 1999/06/06 20:45:39 steve
|
||||
* Add parse and elaboration of non-blocking assignments,
|
||||
* Replace list<PCase::Item*> with an svector version,
|
||||
* Add integer support.
|
||||
*
|
||||
* Revision 1.22 1999/06/02 15:38:46 steve
|
||||
* Line information with nets.
|
||||
*
|
||||
* Revision 1.21 1999/05/31 15:45:59 steve
|
||||
* makegates infinite loop fixed.
|
||||
*
|
||||
* Revision 1.20 1999/05/29 02:36:17 steve
|
||||
* module parameter bind by name.
|
||||
*
|
||||
* Revision 1.19 1999/05/20 04:31:45 steve
|
||||
* Much expression parsing work,
|
||||
* mark continuous assigns with source line info,
|
||||
* replace some assertion failures with Sorry messages.
|
||||
*
|
||||
* Revision 1.18 1999/05/16 05:08:42 steve
|
||||
* Redo constant expression detection to happen
|
||||
* after parsing.
|
||||
*
|
||||
* Parse more operators and expressions.
|
||||
*
|
||||
* Revision 1.17 1999/05/10 00:16:58 steve
|
||||
* Parse and elaborate the concatenate operator
|
||||
* in structural contexts, Replace vector<PExpr*>
|
||||
* and list<PExpr*> with svector<PExpr*>, evaluate
|
||||
* constant expressions with parameters, handle
|
||||
* memories as lvalues.
|
||||
*
|
||||
* Parse task declarations, integer types.
|
||||
*
|
||||
* Revision 1.16 1999/05/08 20:19:20 steve
|
||||
* Parse more things.
|
||||
*
|
||||
* Revision 1.15 1999/05/07 04:26:49 steve
|
||||
* Parse more complex continuous assign lvalues.
|
||||
*
|
||||
* Revision 1.14 1999/05/06 04:37:17 steve
|
||||
* Get rid of list<lgate> types.
|
||||
*
|
||||
* Revision 1.13 1999/05/06 04:09:28 steve
|
||||
* Parse more constant expressions.
|
||||
*
|
||||
* Revision 1.12 1999/05/02 23:25:32 steve
|
||||
* Enforce module instance names.
|
||||
*
|
||||
* Revision 1.11 1999/04/19 01:59:37 steve
|
||||
* Add memories to the parse and elaboration phases.
|
||||
*
|
||||
* Revision 1.10 1999/02/21 17:01:57 steve
|
||||
* Add support for module parameters.
|
||||
*
|
||||
* Revision 1.9 1999/02/15 02:06:15 steve
|
||||
* Elaborate gate ranges.
|
||||
*
|
||||
* Revision 1.8 1999/01/25 05:45:56 steve
|
||||
* Add the LineInfo class to carry the source file
|
||||
* location of things. PGate, Statement and PProcess.
|
||||
*
|
||||
* elaborate handles module parameter mismatches,
|
||||
* missing or incorrect lvalues for procedural
|
||||
* assignment, and errors are propogated to the
|
||||
* top of the elaboration call tree.
|
||||
*
|
||||
* Attach line numbers to processes, gates and
|
||||
* assignment statements.
|
||||
*
|
||||
* Revision 1.7 1998/12/09 04:02:47 steve
|
||||
* Support the include directive.
|
||||
*
|
||||
* Revision 1.6 1998/12/01 00:42:14 steve
|
||||
* Elaborate UDP devices,
|
||||
* Support UDP type attributes, and
|
||||
* pass those attributes to nodes that
|
||||
* are instantiated by elaboration,
|
||||
* Put modules into a map instead of
|
||||
* a simple list.
|
||||
*
|
||||
* Revision 1.5 1998/11/25 02:35:53 steve
|
||||
* Parse UDP primitives all the way to pform.
|
||||
*
|
||||
* Revision 1.4 1998/11/23 00:20:23 steve
|
||||
* NetAssign handles lvalues as pin links
|
||||
* instead of a signal pointer,
|
||||
* Wire attributes added,
|
||||
* Ability to parse UDP descriptions added,
|
||||
* XNF generates EXT records for signals with
|
||||
* the PAD attribute.
|
||||
*
|
||||
* Revision 1.3 1998/11/11 00:01:51 steve
|
||||
* Check net ranges in declarations.
|
||||
*
|
||||
* Revision 1.2 1998/11/07 17:05:06 steve
|
||||
* Handle procedural conditional, and some
|
||||
* of the conditional expressions.
|
||||
*
|
||||
* Elaborate signals and identifiers differently,
|
||||
* allowing the netlist to hold signal information.
|
||||
*
|
||||
* Revision 1.1 1998/11/03 23:29:03 steve
|
||||
* Introduce verilog to CVS.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __pform_H
|
||||
#define __pform_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -18,11 +18,12 @@
|
||||
* 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)
|
||||
#ident "$Id: pform.h,v 1.31 1999/09/10 05:02:09 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pform.h,v 1.35 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "named.h"
|
||||
# include "Module.h"
|
||||
# include "Statement.h"
|
||||
# include "PGate.h"
|
||||
@@ -65,9 +66,12 @@ struct vlltype;
|
||||
|
||||
/* This is information about port name information for named port
|
||||
connections. */
|
||||
struct portname_t {
|
||||
string name;
|
||||
PExpr*parm;
|
||||
|
||||
typedef struct named<PExpr*> portname_t;
|
||||
|
||||
struct parmvalue_t {
|
||||
svector<PExpr*>*by_order;
|
||||
svector<portname_t*>*by_name;
|
||||
};
|
||||
|
||||
/* The lgate is gate instantiation information. */
|
||||
@@ -116,6 +120,8 @@ extern void pform_makewire(const struct vlltype&li, const string&name,
|
||||
NetNet::Type type = NetNet::IMPLICIT);
|
||||
extern void pform_makewire(const struct vlltype&li, const list<string>*names,
|
||||
NetNet::Type type);
|
||||
extern void pform_make_reginit(const struct vlltype&li,
|
||||
const string&name, PExpr*expr);
|
||||
extern void pform_set_port_type(list<string>*names, NetNet::PortType);
|
||||
extern void pform_set_net_range(list<string>*names, const svector<PExpr*>*);
|
||||
extern void pform_set_reg_idx(const string&name, PExpr*l, PExpr*r);
|
||||
@@ -142,7 +148,7 @@ extern void pform_makegates(PGBuiltin::Type type,
|
||||
svector<lgate>*gates);
|
||||
|
||||
extern void pform_make_modgates(const string&type,
|
||||
svector<PExpr*>*overrides,
|
||||
struct parmvalue_t*overrides,
|
||||
svector<lgate>*gates);
|
||||
|
||||
/* Make a continuous assignment node, with optional bit- or part- select. */
|
||||
@@ -174,6 +180,18 @@ extern void pform_dump(ostream&out, Module*mod);
|
||||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.35 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.34 2000/01/10 22:16:24 steve
|
||||
* minor type syntax fix for stubborn C++ compilers.
|
||||
*
|
||||
* Revision 1.33 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.32 1999/12/30 19:06:14 steve
|
||||
* Support reg initial assignment syntax.
|
||||
*
|
||||
* Revision 1.31 1999/09/10 05:02:09 steve
|
||||
* Handle integers at task parameters.
|
||||
*
|
||||
|
||||
+45
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: pform_dump.cc,v 1.45 1999/10/10 01:59:55 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pform_dump.cc,v 1.49 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -283,7 +283,10 @@ void PGBuiltin::dump(ostream&out) const
|
||||
void PGModule::dump(ostream&out) const
|
||||
{
|
||||
out << " " << type_ << " ";
|
||||
|
||||
// If parameters are overridden by order, dump them.
|
||||
if (overrides_) {
|
||||
assert(parms_ == 0);
|
||||
out << "#(";
|
||||
out << *((*overrides_)[0]);
|
||||
for (unsigned idx = 1 ; idx < overrides_->count() ; idx += 1) {
|
||||
@@ -291,7 +294,31 @@ void PGModule::dump(ostream&out) const
|
||||
}
|
||||
out << ") ";
|
||||
}
|
||||
out << get_name() << "(";
|
||||
|
||||
// If parameters are overridden by name, dump them.
|
||||
if (parms_) {
|
||||
assert(overrides_ == 0);
|
||||
out << "#(";
|
||||
out << "." << parms_[0].name << "(" << *parms_[0].parm << ")";
|
||||
for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) {
|
||||
out << ", ." << parms_[idx].name << "(" <<
|
||||
*parms_[idx].parm << ")";
|
||||
}
|
||||
out << ") ";
|
||||
}
|
||||
|
||||
out << get_name();
|
||||
|
||||
// If the module is arrayed, print the index expressions.
|
||||
if (msb_ || lsb_) {
|
||||
out << "[";
|
||||
if (msb_) out << *msb_;
|
||||
out << ":";
|
||||
if (lsb_) out << *lsb_;
|
||||
out << "]";
|
||||
}
|
||||
|
||||
out << "(";
|
||||
if (pins_) {
|
||||
out << "." << pins_[0].name << "(";
|
||||
if (pins_[0].parm) out << *pins_[0].parm;
|
||||
@@ -583,11 +610,11 @@ void Module::dump(ostream&out) const
|
||||
}
|
||||
|
||||
// Iterate through and display all the wires.
|
||||
for (list<PWire*>::const_iterator wire = wires_.begin()
|
||||
for (map<string,PWire*>::const_iterator wire = wires_.begin()
|
||||
; wire != wires_.end()
|
||||
; wire ++ ) {
|
||||
|
||||
(*wire)->dump(out);
|
||||
(*wire).second->dump(out);
|
||||
}
|
||||
|
||||
// Dump the task definitions.
|
||||
@@ -675,6 +702,18 @@ void PUdp::dump(ostream&out) const
|
||||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.49 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.48 2000/02/18 05:15:03 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.47 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.46 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.45 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: propinit.cc,v 1.1 1998/12/20 02:05:41 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: propinit.cc,v 1.2 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -81,6 +81,9 @@ void propinit(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: propinit.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1998/12/20 02:05:41 steve
|
||||
* Function to calculate wire initial value.
|
||||
*
|
||||
|
||||
+35
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: set_width.cc,v 1.6 1999/10/05 06:19:46 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: set_width.cc,v 1.9 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -126,7 +126,6 @@ bool NetEBBits::set_width(unsigned w)
|
||||
*/
|
||||
bool NetEBComp::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
return (w == 1);
|
||||
}
|
||||
|
||||
@@ -139,6 +138,15 @@ bool NetEBLogic::set_width(unsigned w)
|
||||
return (w == 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* There is nothing we can do to the operands of a multiply to make it
|
||||
* confirm to the requested width. Force the context to pad or truncate.
|
||||
*/
|
||||
bool NetEBMult::set_width(unsigned w)
|
||||
{
|
||||
return w == expr_width();
|
||||
}
|
||||
|
||||
/*
|
||||
* The shift operator allows the shift amount to have its own
|
||||
* natural width. The width of the operator result is the width of the
|
||||
@@ -176,11 +184,21 @@ bool NetEConcat::set_width(unsigned w)
|
||||
|
||||
bool NetEConst::set_width(unsigned w)
|
||||
{
|
||||
if (w > value_.len())
|
||||
return false;
|
||||
if (w > value_.len()) {
|
||||
verinum tmp (verinum::V0, w);
|
||||
for (unsigned idx = 0 ; idx < value_.len() ; idx += 1)
|
||||
tmp.set(idx, value_[idx]);
|
||||
|
||||
value_ = tmp;
|
||||
|
||||
} else {
|
||||
verinum tmp (verinum::V0, w);
|
||||
for (unsigned idx = 0 ; idx < w ; idx += 1)
|
||||
tmp.set(idx, value_[idx]);
|
||||
|
||||
value_ = tmp;
|
||||
}
|
||||
|
||||
assert(w <= value_.len());
|
||||
value_ = verinum(value_, w);
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
@@ -256,6 +274,15 @@ bool NetEUnary::set_width(unsigned w)
|
||||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.9 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.8 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.7 2000/01/01 19:56:51 steve
|
||||
* Properly expand/shrink constants in expressions.
|
||||
*
|
||||
* Revision 1.6 1999/10/05 06:19:46 steve
|
||||
* Add support for reduction NOR.
|
||||
*
|
||||
|
||||
-189
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998 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)
|
||||
#ident "$Id: sigfold.cc,v 1.3 1999/11/06 04:51:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
/*
|
||||
* Some targets require that a list of connections include exactly one
|
||||
* signal. This processing step deletes excess signals to meet that
|
||||
* requirement.
|
||||
*
|
||||
* If there is a ring that has more then one signal connected
|
||||
* together, the following heuristic is used to choose which signal to
|
||||
* keep:
|
||||
*
|
||||
* If the name of signal X is deeper in the design hierarchy then
|
||||
* signal Y, keep signal Y.
|
||||
*
|
||||
* Else, if X is a bus that is not as wide as Y, keep signal Y.
|
||||
*
|
||||
* The result of this should be that signals of enclosing modules will
|
||||
* be preferred over signals of instantiated modules, and bussed
|
||||
* signals (vectors) will be preferred over scaler signals.
|
||||
*
|
||||
* The presence of attributes modifies the folding process, by placing
|
||||
* restrictions on what is allowed.
|
||||
*
|
||||
* If two signals have an attribute key X, they can be folded
|
||||
* only if X has the same value for both signals.
|
||||
*
|
||||
* If signal A has attribute X and signal B does not, then
|
||||
* signals can be folded if B can take the attribute.
|
||||
*
|
||||
* All the pins in a vector have identical attributes.
|
||||
*/
|
||||
|
||||
static unsigned depth(const string&sym)
|
||||
{
|
||||
unsigned cnt = 0;
|
||||
for (unsigned idx = 0 ; idx < sym.length() ; idx += 1)
|
||||
if (sym[idx] == '.')
|
||||
cnt += 1;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static bool is_any_signal(const NetNet*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void clear_extra_signals(NetNet*net, unsigned npin)
|
||||
{
|
||||
const unsigned mydepth = depth(net->name());
|
||||
NetObj*cur = net;
|
||||
unsigned pin = npin;
|
||||
for (net->pin(pin).next_link(cur, pin) ; cur != net ; ) {
|
||||
|
||||
// sig is the node I am going to try to subsume.
|
||||
NetNet*sig = dynamic_cast<NetNet*>(cur);
|
||||
|
||||
// Skip the node if it isn't even a signal.
|
||||
if (sig == 0) {
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(sig)) {
|
||||
cerr << "internal warning: sigfold found NetTmp--"
|
||||
"deleting it." << endl;
|
||||
|
||||
// save the next link, ...
|
||||
NetObj*nxt;
|
||||
unsigned pnxt;
|
||||
cur->pin(pin).next_link(nxt, pnxt);
|
||||
|
||||
// disconnect the target signal, ...
|
||||
sig->pin(pin).unlink();
|
||||
|
||||
// And onward.
|
||||
cur = nxt;
|
||||
pin = pnxt;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip the node if it has incompatible attributes.
|
||||
if (! net->has_compat_attributes(*sig)) {
|
||||
|
||||
// SPECIAL CASE!
|
||||
if (sig->has_compat_attributes(*net)) {
|
||||
net->pin(npin).unlink();
|
||||
return;
|
||||
}
|
||||
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip the node if it is higher up.
|
||||
if (depth(sig->name()) < mydepth) {
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip the node if it is a larger vector.
|
||||
if (sig->pin_count() > net->pin_count()) {
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
continue;
|
||||
}
|
||||
|
||||
// save the next link, ...
|
||||
NetObj*nxt;
|
||||
unsigned pnxt;
|
||||
cur->pin(pin).next_link(nxt, pnxt);
|
||||
|
||||
// disconnect the target signal, ...
|
||||
sig->pin(pin).unlink();
|
||||
|
||||
// And onward.
|
||||
cur = nxt;
|
||||
pin = pnxt;
|
||||
}
|
||||
}
|
||||
|
||||
static void delete_if_unconnected(NetNet*net)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
if (net->pin(idx).is_linked())
|
||||
return;
|
||||
|
||||
delete net;
|
||||
}
|
||||
|
||||
void sigfold(Design*des)
|
||||
{
|
||||
des->clear_signal_marks();
|
||||
while (NetNet*obj = des->find_signal(&is_any_signal)) {
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1)
|
||||
clear_extra_signals(obj, idx);
|
||||
obj->set_mark();
|
||||
}
|
||||
|
||||
// After the disconnect step, I may have signals that are not
|
||||
// connected to anything. Delete those.
|
||||
|
||||
des->clear_signal_marks();
|
||||
while (NetNet*obj = des->find_signal(&is_any_signal)) {
|
||||
obj->set_mark();
|
||||
delete_if_unconnected(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sigfold.cc,v $
|
||||
* Revision 1.3 1999/11/06 04:51:11 steve
|
||||
* Catch NetTmp objects.
|
||||
*
|
||||
* Revision 1.2 1998/12/02 04:37:13 steve
|
||||
* Add the nobufz function to eliminate bufz objects,
|
||||
* Object links are marked with direction,
|
||||
* constant propagation is more careful with wide links,
|
||||
* Signal folding is aware of attributes, and
|
||||
* the XNF target can dump UDP objects based on LCA
|
||||
* attributes.
|
||||
*
|
||||
* Revision 1.1 1998/11/16 05:03:53 steve
|
||||
* Add the sigfold function that unlinks excess
|
||||
* signal nodes, and add the XNF target.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
* 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)
|
||||
#ident "$Id: sref.h,v 1.4 1999/08/05 04:58:17 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sref.h,v 1.5 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <assert.h>
|
||||
@@ -146,6 +146,9 @@ template <class T1, class T2> void sref_back<T1,T2>::desert_(sref<T1,T2>*item)
|
||||
|
||||
/*
|
||||
* $Log: sref.h,v $
|
||||
* Revision 1.5 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 1999/08/05 04:58:17 steve
|
||||
* Fix compile error with gcc 2.95
|
||||
*
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
* 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)
|
||||
#ident "$Id: svector.h,v 1.4 1999/06/15 03:44:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: svector.h,v 1.5 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <assert.h>
|
||||
@@ -97,6 +97,9 @@ template <class TYPE> class svector {
|
||||
|
||||
/*
|
||||
* $Log: svector.h,v $
|
||||
* Revision 1.5 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: synth.cc,v 1.3 1999/12/01 06:06:16 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: synth.cc,v 1.6 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -39,6 +39,14 @@
|
||||
* always @(posedge CLK) if (CE) Q = D;
|
||||
* always @(negedge CLK) if (CE) Q = D;
|
||||
*
|
||||
* These are memory assignments:
|
||||
*
|
||||
* always @(posedge CLK) M[a] = D
|
||||
* always @(negedge CLK) M[a] = D
|
||||
*
|
||||
* always @(posedge CLK) if (CE) M[a] = D;
|
||||
* always @(negedge CLK) if (CE) M[a] = D;
|
||||
*
|
||||
* The r-value of the assignments must be identifiers (i.e. wires or
|
||||
* registers) and the CE must be single-bit identifiers. The generated
|
||||
* device will be wide enough to accomodate Q and D.
|
||||
@@ -48,7 +56,7 @@ class match_dff : public proc_match_t {
|
||||
public:
|
||||
match_dff(Design*d, NetProcTop*t)
|
||||
: des_(d), top_(t), pclk_(0), nclk_(0), con_(0), ce_(0),
|
||||
asn_(0), d_(0)
|
||||
asn_(0), asm_(0), d_(0)
|
||||
{ }
|
||||
|
||||
~match_dff() { }
|
||||
@@ -56,7 +64,11 @@ class match_dff : public proc_match_t {
|
||||
void make_it();
|
||||
|
||||
private:
|
||||
void make_dff_();
|
||||
void make_ram_();
|
||||
|
||||
virtual int assign(NetAssign*);
|
||||
virtual int assign_mem(NetAssignMem*);
|
||||
virtual int condit(NetCondit*);
|
||||
virtual int pevent(NetPEvent*);
|
||||
|
||||
@@ -67,7 +79,9 @@ class match_dff : public proc_match_t {
|
||||
|
||||
NetCondit *con_;
|
||||
NetNet*ce_;
|
||||
|
||||
NetAssign *asn_;
|
||||
NetAssignMem*asm_;
|
||||
|
||||
NetNet*d_;
|
||||
};
|
||||
@@ -76,7 +90,7 @@ int match_dff::assign(NetAssign*as)
|
||||
{
|
||||
if (!pclk_)
|
||||
return 0;
|
||||
if (asn_)
|
||||
if (asn_ || asm_)
|
||||
return 0;
|
||||
|
||||
asn_ = as;
|
||||
@@ -87,11 +101,26 @@ int match_dff::assign(NetAssign*as)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int match_dff::assign_mem(NetAssignMem*as)
|
||||
{
|
||||
if (!pclk_)
|
||||
return 0;
|
||||
if (asn_ || asm_)
|
||||
return 0;
|
||||
|
||||
asm_ = as;
|
||||
d_ = asm_->rval()->synthesize(des_);
|
||||
if (d_ == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int match_dff::condit(NetCondit*co)
|
||||
{
|
||||
if (!pclk_)
|
||||
return 0;
|
||||
if (con_ || asn_)
|
||||
if (con_ || asn_ || asm_)
|
||||
return 0;
|
||||
|
||||
con_ = co;
|
||||
@@ -106,7 +135,7 @@ int match_dff::condit(NetCondit*co)
|
||||
|
||||
int match_dff::pevent(NetPEvent*pe)
|
||||
{
|
||||
if (pclk_ || con_ || asn_)
|
||||
if (pclk_ || con_ || asn_ || asm_)
|
||||
return 0;
|
||||
|
||||
pclk_ = pe;
|
||||
@@ -125,6 +154,17 @@ int match_dff::pevent(NetPEvent*pe)
|
||||
}
|
||||
|
||||
void match_dff::make_it()
|
||||
{
|
||||
if (asn_) {
|
||||
assert(asm_ == 0);
|
||||
make_dff_();
|
||||
} else {
|
||||
assert(asm_);
|
||||
make_ram_();
|
||||
}
|
||||
}
|
||||
|
||||
void match_dff::make_dff_()
|
||||
{
|
||||
NetFF*ff = new NetFF(asn_->name(), asn_->pin_count());
|
||||
|
||||
@@ -143,6 +183,43 @@ void match_dff::make_it()
|
||||
des_->add_node(ff);
|
||||
}
|
||||
|
||||
void match_dff::make_ram_()
|
||||
{
|
||||
NetMemory*mem = asm_->memory();
|
||||
NetNet*adr = asm_->index();
|
||||
NetRamDq*ram = new NetRamDq(des_->local_symbol(mem->name()), mem,
|
||||
adr->pin_count());
|
||||
for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
|
||||
connect(adr->pin(idx), ram->pin_Address(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < ram->width() ; idx += 1)
|
||||
connect(ram->pin_Data(idx), d_->pin(idx));
|
||||
|
||||
if (ce_)
|
||||
connect(ram->pin_WE(), ce_->pin(0));
|
||||
|
||||
assert(nclk_->type() == NetNEvent::POSEDGE);
|
||||
connect(ram->pin_InClock(), nclk_->pin(0));
|
||||
|
||||
ram->absorb_partners();
|
||||
des_->add_node(ram);
|
||||
}
|
||||
|
||||
class match_block : public proc_match_t {
|
||||
|
||||
public:
|
||||
match_block(Design*d, NetProcTop*t)
|
||||
: des_(d), top_(t)
|
||||
{ }
|
||||
|
||||
~match_block() { }
|
||||
|
||||
private:
|
||||
|
||||
Design*des_;
|
||||
NetProcTop*top_;
|
||||
};
|
||||
|
||||
class synth_f : public functor_t {
|
||||
|
||||
public:
|
||||
@@ -180,6 +257,11 @@ void synth_f::proc_always_(class Design*des)
|
||||
des->delete_process(top_);
|
||||
return;
|
||||
}
|
||||
|
||||
match_block block_pat(des, top_);
|
||||
if (top_->statement()->match_proc(&block_pat)) {
|
||||
cerr << "XXXX: recurse and return here" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -191,6 +273,15 @@ void synth(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: synth.cc,v $
|
||||
* Revision 1.6 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.5 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.4 1999/12/05 02:24:09 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.3 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: t-null.cc,v 1.8 1999/10/05 03:26:37 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-null.cc,v 1.10 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -35,6 +35,7 @@ static class target_null_t : public target_t {
|
||||
void task_def(ostream&, const NetTaskDef*) { }
|
||||
void net_assign(ostream&os, const NetAssign*) { }
|
||||
void net_assign_nb(ostream&os, const NetAssignNB*) { }
|
||||
void net_const(ostream&, const NetConst*) { }
|
||||
void net_esignal(ostream&, const NetESignal*) { }
|
||||
void net_event(ostream&, const NetNEvent*) { }
|
||||
bool proc_block(ostream&, const NetBlock*) { return true; }
|
||||
@@ -51,6 +52,12 @@ static class target_null_t : public target_t {
|
||||
extern const struct target tgt_null = { "null", &target_null_obj };
|
||||
/*
|
||||
* $Log: t-null.cc,v $
|
||||
* Revision 1.10 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/02/14 06:04:52 steve
|
||||
* Unary reduction operators do not set their operand width
|
||||
*
|
||||
* Revision 1.8 1999/10/05 03:26:37 steve
|
||||
* null target ignore assignment nodes.
|
||||
*
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-1999 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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: t-verilog.cc,v 1.8 1999/09/22 16:57:24 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-verilog.cc,v 1.9 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -272,6 +272,9 @@ const struct target tgt_verilog = {
|
||||
|
||||
/*
|
||||
* $Log: t-verilog.cc,v $
|
||||
* Revision 1.9 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.8 1999/09/22 16:57:24 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: t-vvm.cc,v 1.87 1999/12/02 16:58:58 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-vvm.cc,v 1.104 2000/02/24 01:57:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
@@ -52,6 +52,7 @@ class target_vvm : public target_t {
|
||||
|
||||
public:
|
||||
target_vvm();
|
||||
~target_vvm();
|
||||
|
||||
virtual void start_design(ostream&os, const Design*);
|
||||
virtual void scope(ostream&os, const NetScope*);
|
||||
@@ -64,6 +65,7 @@ class target_vvm : public target_t {
|
||||
virtual void lpm_clshift(ostream&os, const NetCLShift*);
|
||||
virtual void lpm_compare(ostream&os, const NetCompare*);
|
||||
virtual void lpm_ff(ostream&os, const NetFF*);
|
||||
virtual void lpm_mult(ostream&os, const NetMult*);
|
||||
virtual void lpm_mux(ostream&os, const NetMux*);
|
||||
virtual void lpm_ram_dq(ostream&os, const NetRamDq*);
|
||||
|
||||
@@ -78,9 +80,12 @@ class target_vvm : public target_t {
|
||||
virtual void proc_assign(ostream&os, const NetAssign*);
|
||||
virtual void proc_assign_mem(ostream&os, const NetAssignMem*);
|
||||
virtual void proc_assign_nb(ostream&os, const NetAssignNB*);
|
||||
virtual void proc_assign_mem_nb(ostream&os, const NetAssignMemNB*);
|
||||
virtual bool proc_block(ostream&os, const NetBlock*);
|
||||
virtual void proc_case(ostream&os, const NetCase*net);
|
||||
void proc_case_fun(ostream&os, const NetCase*net);
|
||||
virtual void proc_condit(ostream&os, const NetCondit*);
|
||||
void proc_condit_fun(ostream&os, const NetCondit*);
|
||||
virtual void proc_forever(ostream&os, const NetForever*);
|
||||
virtual void proc_repeat(ostream&os, const NetRepeat*);
|
||||
virtual void proc_stask(ostream&os, const NetSTask*);
|
||||
@@ -94,6 +99,7 @@ class target_vvm : public target_t {
|
||||
void end_process(ostream&os, const NetProcTop*);
|
||||
|
||||
private:
|
||||
void emit_init_value_(const NetObj::Link&lnk, verinum::V val);
|
||||
void emit_gate_outputfun_(const NetNode*, unsigned);
|
||||
string defn_gate_outputfun_(ostream&os, const NetNode*, unsigned);
|
||||
|
||||
@@ -101,6 +107,13 @@ class target_vvm : public target_t {
|
||||
// being generated.
|
||||
string thread_class_;
|
||||
|
||||
// This flag is true if we are writing out a function
|
||||
// definition. Thread steps are not available within
|
||||
// functions, and certain constructs are handled
|
||||
// differently. A flag is enough because function definitions
|
||||
// cannot nest.
|
||||
bool function_def_flag_;
|
||||
|
||||
// Method definitions go into this file.
|
||||
char*defn_name;
|
||||
ofstream defn;
|
||||
@@ -133,10 +146,15 @@ class target_vvm : public target_t {
|
||||
|
||||
|
||||
target_vvm::target_vvm()
|
||||
: delayed_name(0), init_code_name(0)
|
||||
: function_def_flag_(false), delayed_name(0), init_code_name(0)
|
||||
{
|
||||
}
|
||||
|
||||
target_vvm::~target_vvm()
|
||||
{
|
||||
assert(function_def_flag_ == false);
|
||||
}
|
||||
|
||||
/*
|
||||
* This class emits code for the rvalue of a procedural
|
||||
* assignment. The expression is evaluated to fit the width
|
||||
@@ -242,6 +260,7 @@ void vvm_proc_rval::expr_ident(const NetEIdent*expr)
|
||||
void vvm_proc_rval::expr_memory(const NetEMemory*mem)
|
||||
{
|
||||
const string mname = mangle(mem->name());
|
||||
assert(mem->index());
|
||||
mem->index()->expr_scan(this);
|
||||
result = mname + ".get_word(" + result + ".as_unsigned())";
|
||||
}
|
||||
@@ -314,7 +333,7 @@ void vvm_proc_rval::expr_ufunc(const NetEUFunc*expr)
|
||||
}
|
||||
|
||||
/* Make the function call. */
|
||||
os_ << " " << mangle(expr->name()) << "(sim_);" << endl;
|
||||
os_ << " " << mangle(expr->name()) << "();" << endl;
|
||||
|
||||
/* Save the return value in a temporary. */
|
||||
result = make_temp();
|
||||
@@ -425,10 +444,15 @@ void vvm_proc_rval::expr_binary(const NetEBinary*expr)
|
||||
case 'o': // logical or (||)
|
||||
os_ << setw(indent_) << "" << result << " = vvm_binop_lor("
|
||||
<< lres << "," << rres << ");" << endl;
|
||||
break;
|
||||
case 'r': // right shift(>>)
|
||||
os_ << setw(indent_) << "" << result << " = vvm_binop_shiftr("
|
||||
<< lres << "," << rres << ");" << endl;
|
||||
break;
|
||||
case 'X':
|
||||
os_ << setw(indent_) << "" << result << " = vvm_binop_xnor("
|
||||
<< lres << "," << rres << ");" << endl;
|
||||
break;
|
||||
case '+':
|
||||
os_ << setw(indent_) << "" << result << " = vvm_binop_plus("
|
||||
<< lres << "," << rres << ");" << endl;
|
||||
@@ -449,6 +473,18 @@ void vvm_proc_rval::expr_binary(const NetEBinary*expr)
|
||||
os_ << setw(indent_) << "" << result << " = vvm_binop_xor("
|
||||
<< lres << "," << rres << ");" << endl;
|
||||
break;
|
||||
case '*':
|
||||
os_ << setw(indent_) << "" << "vvm_binop_mult(" << result
|
||||
<< "," << lres << "," << rres << ");" << endl;
|
||||
break;
|
||||
case '/':
|
||||
os_ << setw(indent_) << "" << result << " = vvm_binop_idiv("
|
||||
<< lres << "," << rres << ");" << endl;
|
||||
break;
|
||||
case '%':
|
||||
os_ << setw(indent_) << "" << result << " = vvm_binop_imod("
|
||||
<< lres << "," << rres << ");" << endl;
|
||||
break;
|
||||
default:
|
||||
cerr << "vvm: Unhandled binary op `" << expr->op() << "': "
|
||||
<< *expr << endl;
|
||||
@@ -560,8 +596,31 @@ void vvm_parm_rval::expr_ident(const NetEIdent*expr)
|
||||
|
||||
void vvm_parm_rval::expr_memory(const NetEMemory*mem)
|
||||
{
|
||||
assert(mem->index() == 0);
|
||||
result = string("&") + mangle(mem->name()) + ".base";
|
||||
if (mem->index() == 0) {
|
||||
/* If the expression is a memory without an index, then
|
||||
return the handle for the memory object. System tasks
|
||||
can take such things as parameters. */
|
||||
result = string("&") + mangle(mem->name()) + ".base";
|
||||
|
||||
} else if (const NetEConst*idx = dynamic_cast<const NetEConst*>(mem->index())){
|
||||
|
||||
/* If the expression is a memory with a constant index,
|
||||
then generate a call to vpi_handle_by_index() to get
|
||||
the memory word handle. */
|
||||
unsigned long val = idx->value().as_ulong();
|
||||
ostrstream res;
|
||||
res << "vpi_handle_by_index(&" << mangle(mem->name()) <<
|
||||
".base, " << val << ")" << ends;
|
||||
result = res.str();
|
||||
|
||||
} else {
|
||||
|
||||
/* Otherwise, evaluate the index at run time and use
|
||||
that to select the memory word. */
|
||||
string rval = emit_proc_rval(tgt_->defn, 6, mem->index());
|
||||
result = "vpi_handle_by_index(&" + mangle(mem->name()) +
|
||||
".base, " + rval + ".as_unsigned())";
|
||||
}
|
||||
}
|
||||
|
||||
void vvm_parm_rval::expr_scope(const NetEScope*escope)
|
||||
@@ -608,14 +667,16 @@ void target_vvm::start_design(ostream&os, const Design*mod)
|
||||
string_counter = 1;
|
||||
number_counter = 1;
|
||||
|
||||
#if 0
|
||||
os << "static struct __vpiStringConst string_table[];" << endl;
|
||||
os << "static struct __vpiNumberConst number_table[];" << endl;
|
||||
#endif
|
||||
|
||||
init_code << "static void design_init(vvm_simulation&sim)" << endl;
|
||||
init_code << "static void design_init()" << endl;
|
||||
init_code << "{" << endl;
|
||||
init_code << " vpip_init_simulation();"
|
||||
<< endl;
|
||||
start_code << "static void design_start(vvm_simulation&sim)" << endl;
|
||||
start_code << "static void design_start()" << endl;
|
||||
start_code << "{" << endl;
|
||||
}
|
||||
|
||||
@@ -699,16 +760,28 @@ void target_vvm::end_design(ostream&os, const Design*mod)
|
||||
if (vpi_module_path.length() > 0)
|
||||
os << " vvm_set_module_path(\"" << vpi_module_path <<
|
||||
"\");" << endl;
|
||||
os << " vvm_load_vpi_module(\"system.vpi\");" << endl;
|
||||
os << " vvm_simulation sim;" << endl;
|
||||
os << " design_init(sim);" << endl;
|
||||
os << " design_start(sim);" << endl;
|
||||
|
||||
string vpi_module_list = mod->get_flag("VPI_MODULE_LIST");
|
||||
while (vpi_module_list.length()) {
|
||||
string name;
|
||||
unsigned pos = vpi_module_list.find(',');
|
||||
if (pos < vpi_module_list.length()) {
|
||||
name = vpi_module_list.substr(0, pos);
|
||||
vpi_module_list = vpi_module_list.substr(pos+1);
|
||||
} else {
|
||||
name = vpi_module_list;
|
||||
vpi_module_list = "";
|
||||
}
|
||||
os << " vvm_load_vpi_module(\"" << name << ".vpi\");" << endl;
|
||||
}
|
||||
os << " design_init();" << endl;
|
||||
os << " design_start();" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < process_counter ; idx += 1)
|
||||
os << " thread" << (idx+1) << "_t thread_" <<
|
||||
(idx+1) << "(&sim);" << endl;
|
||||
(idx+1) << ";" << endl;
|
||||
|
||||
os << " sim.run();" << endl;
|
||||
os << " vpip_simulation_run();" << endl;
|
||||
os << "}" << endl;
|
||||
}
|
||||
|
||||
@@ -745,36 +818,12 @@ void target_vvm::signal(ostream&os, const NetNet*sig)
|
||||
if (sig->get_ival(idx) == verinum::Vz)
|
||||
continue;
|
||||
|
||||
map<string,bool>written;
|
||||
|
||||
init_code << " " << mangle(sig->name()) << ".init_P("
|
||||
<< idx << ", V" << sig->get_ival(idx) << ");"
|
||||
<< endl;
|
||||
|
||||
for (const NetObj::Link*lnk = sig->pin(idx).next_link()
|
||||
; (*lnk) != sig->pin(idx) ; lnk = lnk->next_link()) {
|
||||
|
||||
if (lnk->get_dir() == NetObj::Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
// Check to see if the name has already been
|
||||
// written to. This can happen if the object is a
|
||||
// NetESignal, because there can be many of them
|
||||
// with the same name.
|
||||
if (written[lnk->get_obj()->name()])
|
||||
continue;
|
||||
|
||||
written[lnk->get_obj()->name()] = true;
|
||||
|
||||
|
||||
if (dynamic_cast<const NetNode*>(lnk->get_obj())) {
|
||||
init_code << " " <<
|
||||
mangle(lnk->get_obj()->name()) <<
|
||||
".init_" << lnk->get_name() << "(" <<
|
||||
lnk->get_inst() << ", V" <<
|
||||
sig->get_ival(idx) << ");" << endl;
|
||||
}
|
||||
}
|
||||
// Propogate the initial value to inputs throughout.
|
||||
emit_init_value_(sig->pin(idx), sig->get_ival(idx));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,8 +847,9 @@ void target_vvm::task_def(ostream&os, const NetTaskDef*def)
|
||||
|
||||
os << "class " << name << " : public vvm_thread {" << endl;
|
||||
os << " public:" << endl;
|
||||
os << " " << name << "(vvm_simulation*sim, vvm_thread*th)" << endl;
|
||||
os << " : vvm_thread(sim), back_(th), step_(&" << name << "::step_0_)" << endl;
|
||||
os << " " << name << "(vvm_thread*th)" << endl;
|
||||
os << " : vvm_thread(), back_(th), step_(&" << name <<
|
||||
"::step_0_), callee_(0)" << endl;
|
||||
os << " { }" << endl;
|
||||
os << " ~" << name << "() { }" << endl;
|
||||
os << " bool go() { return (this->*step_)(); }" << endl;
|
||||
@@ -812,7 +862,7 @@ void target_vvm::task_def(ostream&os, const NetTaskDef*def)
|
||||
|
||||
defn << "bool " << thread_class_ << "::step_0_() {" << endl;
|
||||
def->proc()->emit_proc(os, this);
|
||||
defn << " sim_->thread_active(back_);" << endl;
|
||||
defn << " back_ -> thread_yield();" << endl;
|
||||
defn << " return false;" << endl;
|
||||
defn << "}" << endl;
|
||||
|
||||
@@ -832,14 +882,23 @@ void target_vvm::func_def(ostream&os, const NetFuncDef*def)
|
||||
{
|
||||
thread_step_ = 0;
|
||||
const string name = mangle(def->name());
|
||||
|
||||
// Flag that we are now in a function definition. Note that
|
||||
// function definitions cannot nest.
|
||||
assert(! function_def_flag_);
|
||||
function_def_flag_ = true;
|
||||
|
||||
os << "// Function " << def->name() << endl;
|
||||
os << "static void " << name << "(vvm_simulation*);" << endl;
|
||||
os << "static void " << name << "();" << endl;
|
||||
|
||||
defn << "// Function " << def->name() << endl;
|
||||
defn << "static void " << name << "(vvm_simulation*sim_)" << endl;
|
||||
defn << "static void " << name << "()" << endl;
|
||||
defn << "{" << endl;
|
||||
def->proc()->emit_proc(os, this);
|
||||
defn << "}" << endl;
|
||||
|
||||
assert(function_def_flag_);
|
||||
function_def_flag_ = false;
|
||||
}
|
||||
|
||||
string target_vvm::defn_gate_outputfun_(ostream&os,
|
||||
@@ -853,10 +912,44 @@ string target_vvm::defn_gate_outputfun_(ostream&os,
|
||||
"_" << lnk.get_inst() << ends;
|
||||
string name = tmp.str();
|
||||
|
||||
os << "static void " << name << "(vvm_simulation*, vpip_bit_t);" << endl;
|
||||
os << "static void " << name << "(vpip_bit_t);" << endl;
|
||||
return name;
|
||||
}
|
||||
|
||||
void target_vvm::emit_init_value_(const NetObj::Link&lnk, verinum::V val)
|
||||
{
|
||||
map<string,bool>written;
|
||||
|
||||
for (const NetObj::Link*cur = lnk.next_link()
|
||||
; (*cur) != lnk ; cur = cur->next_link()) {
|
||||
|
||||
if (cur->get_dir() == NetObj::Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
if (! dynamic_cast<const NetObj*>(cur->get_obj()))
|
||||
continue;
|
||||
|
||||
// Build an init statement for the link, that writes the
|
||||
// value.
|
||||
ostrstream line;
|
||||
line << " " << mangle(cur->get_obj()->name()) <<
|
||||
".init_" << cur->get_name() << "(" <<
|
||||
cur->get_inst() << ", V" << val << ");" << endl << ends;
|
||||
|
||||
|
||||
// Check to see if the line has already been
|
||||
// written to. This can happen if the object is a
|
||||
// NetESignal, because there can be many of them
|
||||
// with the same name.
|
||||
if (written[line.str()])
|
||||
continue;
|
||||
|
||||
written[line.str()] = true;
|
||||
|
||||
init_code << line.str();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This method handles writing output functions for gates that have a
|
||||
* single output (at pin 0). This writes the output_fun method into
|
||||
@@ -868,7 +961,7 @@ void target_vvm::emit_gate_outputfun_(const NetNode*gate, unsigned gpin)
|
||||
|
||||
delayed << "static void " << mangle(gate->name()) <<
|
||||
"_output_" << lnk.get_name() << "_" << lnk.get_inst() <<
|
||||
"(vvm_simulation*sim, vpip_bit_t val)" <<
|
||||
"(vpip_bit_t val)" <<
|
||||
endl << "{" << endl;
|
||||
|
||||
/* The output function connects to gpin of the netlist part
|
||||
@@ -878,21 +971,24 @@ void target_vvm::emit_gate_outputfun_(const NetNode*gate, unsigned gpin)
|
||||
const NetObj*cur;
|
||||
unsigned pin;
|
||||
gate->pin(gpin).next_link(cur, pin);
|
||||
while (cur != gate) {
|
||||
for ( ; cur != gate ; cur->pin(pin).next_link(cur, pin)) {
|
||||
|
||||
// Skip pins that are output only.
|
||||
if (cur->pin(pin).get_dir() == NetObj::Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
if (cur->pin(pin).get_name() != "") {
|
||||
|
||||
delayed << " " << mangle(cur->name()) << ".set_"
|
||||
<< cur->pin(pin).get_name() << "(sim, " <<
|
||||
<< cur->pin(pin).get_name() << "(" <<
|
||||
cur->pin(pin).get_inst() << ", val);" << endl;
|
||||
|
||||
} else {
|
||||
|
||||
delayed << " " << mangle(cur->name()) << ".set(sim, "
|
||||
delayed << " " << mangle(cur->name()) << ".set("
|
||||
<< pin << ", val);" << endl;
|
||||
}
|
||||
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
}
|
||||
|
||||
delayed << "}" << endl;
|
||||
@@ -911,6 +1007,15 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
||||
emit_gate_outputfun_(gate, pin);
|
||||
}
|
||||
|
||||
// Connect the carry output if necessary.
|
||||
if (gate->pin_Cout().is_linked()) {
|
||||
unsigned pin = gate->pin_Cout().get_pin();
|
||||
string outfun = defn_gate_outputfun_(os, gate, pin);
|
||||
init_code << " " << mangle(gate->name()) <<
|
||||
".config_cout(&" << outfun << ");" << endl;
|
||||
emit_gate_outputfun_(gate, pin);
|
||||
}
|
||||
|
||||
if (gate->attribute("LPM_Direction") == "ADD") {
|
||||
init_code << " " << mangle(gate->name()) <<
|
||||
".init_Add_Sub(0, V1);" << endl;
|
||||
@@ -920,6 +1025,8 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
||||
".init_Add_Sub(0, V0);" << endl;
|
||||
|
||||
}
|
||||
|
||||
start_code << " " << mangle(gate->name()) << ".start();" << endl;
|
||||
}
|
||||
|
||||
void target_vvm::lpm_clshift(ostream&os, const NetCLShift*gate)
|
||||
@@ -990,6 +1097,23 @@ void target_vvm::lpm_ff(ostream&os, const NetFF*gate)
|
||||
}
|
||||
}
|
||||
|
||||
void target_vvm::lpm_mult(ostream&os, const NetMult*mul)
|
||||
{
|
||||
string mname = mangle(mul->name());
|
||||
os << "static vvm_mult " << mname << "(" << mul->width_r() <<
|
||||
"," << mul->width_a() << "," << mul->width_b() << "," <<
|
||||
mul->width_s() << ");" << endl;
|
||||
|
||||
// Write the output functions for the multiplier device.
|
||||
for (unsigned idx = 0 ; idx < mul->width_r() ; idx += 1) {
|
||||
unsigned pin = mul->pin_Result(idx).get_pin();
|
||||
string outfun = defn_gate_outputfun_(os, mul, pin);
|
||||
init_code << " " << mangle(mul->name()) <<
|
||||
".config_rout(" << idx << ", &" << outfun << ");" << endl;
|
||||
emit_gate_outputfun_(mul, pin);
|
||||
}
|
||||
}
|
||||
|
||||
void target_vvm::lpm_mux(ostream&os, const NetMux*mux)
|
||||
{
|
||||
string mname = mangle(mux->name());
|
||||
@@ -1071,8 +1195,7 @@ void target_vvm::logic(ostream&os, const NetLogic*gate)
|
||||
|
||||
emit_gate_outputfun_(gate, 0);
|
||||
|
||||
start_code << " " << mangle(gate->name()) <<
|
||||
".start(&sim);" << endl;
|
||||
start_code << " " << mangle(gate->name()) << ".start();" << endl;
|
||||
}
|
||||
|
||||
void target_vvm::bufz(ostream&os, const NetBUFZ*gate)
|
||||
@@ -1173,18 +1296,17 @@ void target_vvm::net_assign_nb(ostream&os, const NetAssignNB*net)
|
||||
os << " public:" << endl;
|
||||
|
||||
if (net->bmux()) {
|
||||
os << " " << name << "(vvm_simulation*s, const vvm_bitset_t<"
|
||||
os << " " << name << "(const vvm_bitset_t<"
|
||||
<< iwid << ">&v, unsigned idx)" << endl;
|
||||
os << " : sim_(s), value_(v), idx_(idx) { }" << endl;
|
||||
os << " : value_(v), idx_(idx) { }" << endl;
|
||||
} else {
|
||||
os << " " << name << "(vvm_simulation*s, const vvm_bits_t&v)"
|
||||
os << " " << name << "(const vvm_bits_t&v)"
|
||||
<< endl;
|
||||
os << " : sim_(s), value_(v) { }" << endl;
|
||||
os << " : value_(v) { }" << endl;
|
||||
}
|
||||
os << " void event_function();" << endl;
|
||||
|
||||
os << " private:" << endl;
|
||||
os << " vvm_simulation*sim_;" << endl;
|
||||
os << " vvm_bitset_t<" << iwid << ">value_;" << endl;
|
||||
|
||||
if (net->bmux())
|
||||
@@ -1219,7 +1341,7 @@ void target_vvm::net_assign_nb(ostream&os, const NetAssignNB*net)
|
||||
continue;
|
||||
|
||||
delayed << " " << mangle(cur->name())
|
||||
<< ".set_" << lnk.get_name() << "sim_, "
|
||||
<< ".set_" << lnk.get_name()
|
||||
<< lnk.get_inst() << ", value_[0]);" << endl;
|
||||
}
|
||||
|
||||
@@ -1246,7 +1368,7 @@ void target_vvm::net_assign_nb(ostream&os, const NetAssignNB*net)
|
||||
continue;
|
||||
|
||||
delayed << " " << mangle(cur->name()) <<
|
||||
".set_" << lnk.get_name() << "(sim_, "
|
||||
".set_" << lnk.get_name() << "("
|
||||
<< lnk.get_inst() << ", value_[" <<
|
||||
idx << "]);" << endl;
|
||||
}
|
||||
@@ -1261,7 +1383,7 @@ void target_vvm::net_case_cmp(ostream&os, const NetCaseCmp*gate)
|
||||
|
||||
os << "static void " << mangle(gate->name()) <<
|
||||
"_output_" << lnk.get_name() << "_" << lnk.get_inst() <<
|
||||
"(vvm_simulation*, vpip_bit_t);" << endl;
|
||||
"(vpip_bit_t);" << endl;
|
||||
|
||||
assert(gate->pin_count() == 3);
|
||||
os << "static vvm_eeq" << "<" << gate->rise_time() << "> "
|
||||
@@ -1270,8 +1392,7 @@ void target_vvm::net_case_cmp(ostream&os, const NetCaseCmp*gate)
|
||||
|
||||
emit_gate_outputfun_(gate, 0);
|
||||
|
||||
start_code << " " << mangle(gate->name()) <<
|
||||
".start(&sim);" << endl;
|
||||
start_code << " " << mangle(gate->name()) << ".start();" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1282,29 +1403,8 @@ void target_vvm::net_case_cmp(ostream&os, const NetCaseCmp*gate)
|
||||
*/
|
||||
void target_vvm::net_const(ostream&os, const NetConst*gate)
|
||||
{
|
||||
string outfun = defn_gate_outputfun_(os, gate, 0);
|
||||
|
||||
os << "static vvm_bufz " << mangle(gate->name()) << "(&" <<
|
||||
outfun << ");" << endl;
|
||||
|
||||
init_code << " " << mangle(gate->name()) << ".set(&sim, 1, ";
|
||||
switch (gate->value()) {
|
||||
case verinum::V0:
|
||||
init_code << "V0";
|
||||
break;
|
||||
case verinum::V1:
|
||||
init_code << "V1";
|
||||
break;
|
||||
case verinum::Vx:
|
||||
init_code << "Vx";
|
||||
break;
|
||||
case verinum::Vz:
|
||||
init_code << "Vz";
|
||||
break;
|
||||
}
|
||||
init_code << ");" << endl;
|
||||
|
||||
emit_gate_outputfun_(gate, 0);
|
||||
for (unsigned idx = 0 ; idx < gate->pin_count() ; idx += 1)
|
||||
emit_init_value_(gate->pin(idx), gate->value(idx));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1357,9 +1457,9 @@ void target_vvm::start_process(ostream&os, const NetProcTop*proc)
|
||||
os << "class " << thread_class_ << " : public vvm_thread {" << endl;
|
||||
|
||||
os << " public:" << endl;
|
||||
os << " " << thread_class_ << "(vvm_simulation*sim)" << endl;
|
||||
os << " : vvm_thread(sim), step_(&" << thread_class_ <<
|
||||
"::step_0_)" << endl;
|
||||
os << " " << thread_class_ << "()" << endl;
|
||||
os << " : vvm_thread(), step_(&" << thread_class_ <<
|
||||
"::step_0_), callee_(0)" << endl;
|
||||
os << " { }" << endl;
|
||||
os << " ~" << thread_class_ << "() { }" << endl;
|
||||
os << endl;
|
||||
@@ -1416,7 +1516,7 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
|
||||
written[cur->name()] = true;
|
||||
defn << " " << mangle(cur->name()) <<
|
||||
".set_" << cur->pin(pin).get_name() <<
|
||||
"(sim_, " << cur->pin(pin).get_inst() <<
|
||||
"(" << cur->pin(pin).get_inst() <<
|
||||
", " << rval << "[0]);" << endl;
|
||||
}
|
||||
|
||||
@@ -1452,7 +1552,7 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
|
||||
written[cur->name()] = true;
|
||||
defn << " " << mangle(cur->name()) <<
|
||||
".set_" << cur->pin(pin).get_name() <<
|
||||
"(sim_, " << cur->pin(pin).get_inst() <<
|
||||
"(" << cur->pin(pin).get_inst() <<
|
||||
", " << rval << "[" << idx << "]);" << endl;
|
||||
}
|
||||
}
|
||||
@@ -1466,14 +1566,14 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
|
||||
*/
|
||||
void target_vvm::proc_assign_mem(ostream&os, const NetAssignMem*amem)
|
||||
{
|
||||
string index = emit_proc_rval(defn, 8, amem->index());
|
||||
string index = mangle(amem->index()->name()) + "_bits";
|
||||
string rval = emit_proc_rval(defn, 8, amem->rval());
|
||||
const NetMemory*mem = amem->memory();
|
||||
|
||||
defn << " /* " << amem->get_line() << " */" << endl;
|
||||
if (mem->width() == amem->rval()->expr_width()) {
|
||||
defn << " " << mangle(mem->name()) <<
|
||||
".set_word(sim_, " << index << ".as_unsigned(), " <<
|
||||
".set_word(" << index << ".as_unsigned(), " <<
|
||||
rval << ");" << endl;
|
||||
|
||||
} else {
|
||||
@@ -1485,7 +1585,7 @@ void target_vvm::proc_assign_mem(ostream&os, const NetAssignMem*amem)
|
||||
defn << " " << tmp << "[" << idx << "] = " <<
|
||||
rval << "[" << idx << "];" << endl;
|
||||
|
||||
defn << " " << mangle(mem->name()) << ".set_word(sim_, "
|
||||
defn << " " << mangle(mem->name()) << ".set_word("
|
||||
<< index << ".as_unsigned(), " << tmp << ");" << endl;
|
||||
}
|
||||
}
|
||||
@@ -1496,14 +1596,45 @@ void target_vvm::proc_assign_nb(ostream&os, const NetAssignNB*net)
|
||||
|
||||
if (net->bmux()) {
|
||||
string bval = emit_proc_rval(defn, 8, net->bmux());
|
||||
defn << " sim_->insert_event(" << net->rise_time()
|
||||
<< ", new " << mangle(net->name()) << "(sim_, " << rval
|
||||
<< ", " << bval << ".as_unsigned()));" << endl;
|
||||
defn << " (new " << mangle(net->name()) << "("
|
||||
<< rval << ", " << bval << ".as_unsigned())) "
|
||||
<< "-> schedule(" << net->rise_time() << ");" << endl;
|
||||
|
||||
} else {
|
||||
defn << " sim_->insert_event(" << net->rise_time()
|
||||
<< ", new " << mangle(net->name()) << "(sim_, " << rval
|
||||
<< "));" << endl;
|
||||
defn << " (new " << mangle(net->name()) << "("
|
||||
<< rval << ")) -> schedule(" << net->rise_time() <<
|
||||
");" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void target_vvm::proc_assign_mem_nb(ostream&os, const NetAssignMemNB*amem)
|
||||
{
|
||||
|
||||
string index = mangle(amem->index()->name()) + "_bits";
|
||||
string rval = emit_proc_rval(defn, 8, amem->rval());
|
||||
const NetMemory*mem = amem->memory();
|
||||
|
||||
defn << " /* " << amem->get_line() << " */" << endl;
|
||||
if (mem->width() == amem->rval()->expr_width()) {
|
||||
defn << " (new vvm_memory_t<" << mem->width() << ","
|
||||
<< mem->count() << ">::assign_nb(" << mangle(mem->name())
|
||||
<< ", " << index << ".as_unsigned(), " << rval <<
|
||||
")) -> schedule();" << endl;
|
||||
|
||||
} else {
|
||||
|
||||
assert(mem->width() <= amem->rval()->expr_width());
|
||||
string tmp = make_temp();
|
||||
defn << " vvm_bitset_t<" << mem->width() << ">" <<
|
||||
tmp << ";" << endl;
|
||||
for (unsigned idx = 0 ; idx < mem->width() ; idx += 1)
|
||||
defn << " " << tmp << "[" << idx << "] = " <<
|
||||
rval << "[" << idx << "];" << endl;
|
||||
|
||||
defn << " (new vvm_memory_t<" << mem->width() << ","
|
||||
<< mem->count() << ">::assign_nb(" << mangle(mem->name())
|
||||
<< ", " << index << ".as_unsigned(), " << tmp <<
|
||||
")) -> schedule();" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1534,6 +1665,11 @@ bool target_vvm::proc_block(ostream&os, const NetBlock*net)
|
||||
*/
|
||||
void target_vvm::proc_case(ostream&os, const NetCase*net)
|
||||
{
|
||||
if (function_def_flag_) {
|
||||
proc_case_fun(os, net);
|
||||
return;
|
||||
}
|
||||
|
||||
string test_func = "";
|
||||
switch (net->type()) {
|
||||
case NetCase::EQ:
|
||||
@@ -1644,8 +1780,71 @@ void target_vvm::proc_case(ostream&os, const NetCase*net)
|
||||
"_() {" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Within a function definition, the case statement is implemented
|
||||
* differently. Since statements in this context cannot block, we can
|
||||
* use open coded if statements to do all the comparisons.
|
||||
*/
|
||||
void target_vvm::proc_case_fun(ostream&os, const NetCase*net)
|
||||
{
|
||||
string test_func = "";
|
||||
switch (net->type()) {
|
||||
case NetCase::EQ:
|
||||
test_func = "vvm_binop_eeq";
|
||||
break;
|
||||
case NetCase::EQX:
|
||||
test_func = "vvm_binop_xeq";
|
||||
break;
|
||||
case NetCase::EQZ:
|
||||
test_func = "vvm_binop_zeq";
|
||||
break;
|
||||
}
|
||||
|
||||
defn << " /* " << net->get_line() << ": case (" <<
|
||||
*net->expr() << ") */" << endl;
|
||||
|
||||
string expr = emit_proc_rval(defn, 6, net->expr());
|
||||
|
||||
unsigned default_idx = net->nitems();
|
||||
bool prev_flag = false;
|
||||
for (unsigned idx = 0 ; idx < net->nitems() ; idx += 1) {
|
||||
|
||||
// don't emit the default case here. Save it for the
|
||||
// last else clause.
|
||||
if (net->expr(idx) == 0) {
|
||||
default_idx = idx;
|
||||
continue;
|
||||
}
|
||||
|
||||
string guard = emit_proc_rval(defn, 6, net->expr(idx));
|
||||
|
||||
if (prev_flag)
|
||||
defn << " } else";
|
||||
else
|
||||
defn << " ";
|
||||
defn << "if (V1 == " << test_func << "(" <<
|
||||
guard << "," << expr << ")[0]) {" << endl;
|
||||
if (net->stat(idx))
|
||||
net->stat(idx)->emit_proc(os, this);
|
||||
|
||||
prev_flag = true;
|
||||
}
|
||||
|
||||
if ((default_idx < net->nitems()) && net->stat(default_idx)) {
|
||||
defn << " } else {" << endl;
|
||||
net->stat(default_idx)->emit_proc(os, this);
|
||||
}
|
||||
|
||||
defn << " }" << endl;
|
||||
}
|
||||
|
||||
void target_vvm::proc_condit(ostream&os, const NetCondit*net)
|
||||
{
|
||||
if (function_def_flag_) {
|
||||
proc_condit_fun(os, net);
|
||||
return;
|
||||
}
|
||||
|
||||
string expr = emit_proc_rval(defn, 8, net->expr());
|
||||
|
||||
unsigned if_step = ++thread_step_;
|
||||
@@ -1687,6 +1886,19 @@ void target_vvm::proc_condit(ostream&os, const NetCondit*net)
|
||||
"_() {" << endl;
|
||||
}
|
||||
|
||||
void target_vvm::proc_condit_fun(ostream&os, const NetCondit*net)
|
||||
{
|
||||
string expr = emit_proc_rval(defn, 8, net->expr());
|
||||
|
||||
defn << " // " << net->get_line() << ": conditional (if-else)"
|
||||
<< endl;
|
||||
defn << " if (" << expr << "[0] == V1) {" << endl;
|
||||
net->emit_recurse_if(os, this);
|
||||
defn << " } else {" << endl;
|
||||
net->emit_recurse_else(os, this);
|
||||
defn << " }" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
* The forever loop is implemented by starting a basic block, handing
|
||||
* the statement, and putting in a goto to the beginning of the block.
|
||||
@@ -1785,7 +1997,8 @@ void target_vvm::proc_utask(ostream&os, const NetUTask*net)
|
||||
{
|
||||
unsigned out_step = ++thread_step_;
|
||||
const string name = mangle(net->name());
|
||||
defn << " callee_ = new " << name << "(sim_, this);" << endl;
|
||||
defn << " assert(callee_ == 0);" << endl;
|
||||
defn << " callee_ = new " << name << "(this);" << endl;
|
||||
defn << " step_ = &" << thread_class_ << "::step_" <<
|
||||
out_step << "_;" << endl;
|
||||
defn << " return false;" << endl;
|
||||
@@ -1795,6 +2008,7 @@ void target_vvm::proc_utask(ostream&os, const NetUTask*net)
|
||||
defn << "bool " << thread_class_ << "::step_" << out_step <<
|
||||
"_() {" << endl;
|
||||
defn << " delete callee_;" << endl;
|
||||
defn << " callee_ = 0;" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1921,8 +2135,7 @@ void target_vvm::proc_delay(ostream&os, const NetPDelay*proc)
|
||||
thread_step_ += 1;
|
||||
defn << " step_ = &" << thread_class_ << "::step_" <<
|
||||
thread_step_ << "_;" << endl;
|
||||
defn << " sim_->thread_delay(" << proc->delay() << ", this);"
|
||||
<< endl;
|
||||
defn << " thread_yield(" << proc->delay() << ");" << endl;
|
||||
defn << " return false;" << endl;
|
||||
defn << "}" << endl;
|
||||
|
||||
@@ -1958,6 +2171,57 @@ extern const struct target tgt_vvm = {
|
||||
};
|
||||
/*
|
||||
* $Log: t-vvm.cc,v $
|
||||
* Revision 1.104 2000/02/24 01:57:10 steve
|
||||
* I no longer need to declare string and number tables early.
|
||||
*
|
||||
* Revision 1.103 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.102 2000/02/14 01:20:50 steve
|
||||
* Support case in functions.
|
||||
*
|
||||
* Revision 1.101 2000/02/14 00:12:09 steve
|
||||
* support if-else in function definitions.
|
||||
*
|
||||
* Revision 1.100 2000/02/13 19:59:33 steve
|
||||
* Handle selecting memory words at run time.
|
||||
*
|
||||
* Revision 1.99 2000/02/13 19:18:27 steve
|
||||
* Accept memory words as parameter to $display.
|
||||
*
|
||||
* Revision 1.98 2000/01/18 04:53:57 steve
|
||||
* missing break is switch.
|
||||
*
|
||||
* Revision 1.97 2000/01/13 06:05:46 steve
|
||||
* Add the XNOR operator.
|
||||
*
|
||||
* Revision 1.96 2000/01/13 05:11:25 steve
|
||||
* Support for multiple VPI modules.
|
||||
*
|
||||
* Revision 1.95 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.94 2000/01/08 03:09:14 steve
|
||||
* Non-blocking memory writes.
|
||||
*
|
||||
* Revision 1.93 2000/01/02 17:57:56 steve
|
||||
* It is possible for node to initialize several pins of a signal.
|
||||
*
|
||||
* Revision 1.92 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.91 1999/12/16 02:42:15 steve
|
||||
* Simulate carry output on adders.
|
||||
*
|
||||
* Revision 1.90 1999/12/12 19:47:54 steve
|
||||
* Remove the useless vvm_simulation class.
|
||||
*
|
||||
* Revision 1.89 1999/12/12 06:03:14 steve
|
||||
* Allow memories without indices in expressions.
|
||||
*
|
||||
* Revision 1.88 1999/12/05 02:24:09 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.87 1999/12/02 16:58:58 steve
|
||||
* Update case comparison (Eric Aardoom).
|
||||
*
|
||||
@@ -2008,63 +2272,5 @@ extern const struct target tgt_vvm = {
|
||||
*
|
||||
* Revision 1.72 1999/11/06 16:00:17 steve
|
||||
* Put number constants into a static table.
|
||||
*
|
||||
* Revision 1.71 1999/11/01 02:07:41 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.70 1999/10/31 20:08:24 steve
|
||||
* Include subtraction in LPM_ADD_SUB device.
|
||||
*
|
||||
* Revision 1.69 1999/10/31 04:11:28 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
* and instance number.
|
||||
*
|
||||
* Revision 1.68 1999/10/28 21:51:21 steve
|
||||
* gate output pins use vpip_bit_t (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.67 1999/10/28 21:36:00 steve
|
||||
* Get rid of monitor_t and fold __vpiSignal into signal.
|
||||
*
|
||||
* Revision 1.66 1999/10/28 04:48:29 steve
|
||||
* Put strings into a single string table.
|
||||
*
|
||||
* Revision 1.65 1999/10/28 00:47:24 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.64 1999/10/23 16:27:53 steve
|
||||
* assignment to bit select is aa single bit.
|
||||
*
|
||||
* Revision 1.63 1999/10/21 02:15:06 steve
|
||||
* Make generated code ISO legal.
|
||||
*
|
||||
* Revision 1.62 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
* Revision 1.61 1999/10/08 02:00:48 steve
|
||||
* vvm supports unary | operator.
|
||||
*
|
||||
* Revision 1.60 1999/10/07 05:25:34 steve
|
||||
* Add non-const bit select in l-value of assignment.
|
||||
*
|
||||
* Revision 1.59 1999/10/06 01:28:18 steve
|
||||
* The $finish task should work immediately.
|
||||
*
|
||||
* Revision 1.58 1999/10/05 06:19:46 steve
|
||||
* Add support for reduction NOR.
|
||||
*
|
||||
* Revision 1.57 1999/10/05 04:02:10 steve
|
||||
* Relaxed width handling for <= assignment.
|
||||
*
|
||||
* Revision 1.56 1999/10/01 15:26:28 steve
|
||||
* Add some vvm operators from Eric Aardoom.
|
||||
*
|
||||
* Revision 1.55 1999/10/01 03:58:37 steve
|
||||
* More resilient assignment to memory location.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: t-xnf.cc,v 1.18 1999/11/19 03:02:25 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-xnf.cc,v 1.23 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/* XNF BACKEND
|
||||
@@ -77,11 +77,13 @@ class target_xnf : public target_t {
|
||||
public:
|
||||
void start_design(ostream&os, const Design*);
|
||||
void end_design(ostream&os, const Design*);
|
||||
void memory(ostream&os, const NetMemory*);
|
||||
void signal(ostream&os, const NetNet*);
|
||||
|
||||
void lpm_add_sub(ostream&os, const NetAddSub*);
|
||||
void lpm_ff(ostream&os, const NetFF*);
|
||||
void lpm_mux(ostream&os, const NetMux*);
|
||||
void lpm_ram_dq(ostream&os, const NetRamDq*);
|
||||
|
||||
void net_const(ostream&os, const NetConst*);
|
||||
void logic(ostream&os, const NetLogic*);
|
||||
@@ -96,7 +98,7 @@ class target_xnf : public target_t {
|
||||
static void draw_sym_with_lcaname(ostream&os, string lca,
|
||||
const NetNode*net);
|
||||
static void draw_xor(ostream&os, const NetAddSub*, unsigned idx);
|
||||
enum adder_type {FORCE0, LOWER, UPPER, DOUBLE };
|
||||
enum adder_type {FORCE0, LOWER, DOUBLE, LOWER_W_CO, EXAMINE_CI };
|
||||
static void draw_carry(ostream&os, const NetAddSub*, unsigned idx,
|
||||
enum adder_type);
|
||||
|
||||
@@ -295,6 +297,14 @@ void scrape_pad_info(string str, char&dir, unsigned&num)
|
||||
num = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memories are handled by the lpm_ram_dq method, so there is nothing
|
||||
* to do here.
|
||||
*/
|
||||
void target_xnf::memory(ostream&, const NetMemory*)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for signals that have attributes that are pertinent to XNF
|
||||
* files. The most obvious are those that have the PAD attribute.
|
||||
@@ -364,44 +374,43 @@ void target_xnf::draw_carry(ostream &os, const NetAddSub*gate, unsigned idx,
|
||||
"LIBVER=2.0.0" << endl;
|
||||
|
||||
// Less significant bit addends, if any
|
||||
if ( type == LOWER || type == DOUBLE ) {
|
||||
if ( type == LOWER || type == DOUBLE || type == LOWER_W_CO ) {
|
||||
draw_pin(os, "A0", gate->pin_DataA(idx));
|
||||
draw_pin(os, "B0", gate->pin_DataB(idx));
|
||||
}
|
||||
|
||||
// More significant bit addends, if any
|
||||
if ( type == UPPER || type == DOUBLE ) {
|
||||
unsigned int i = (type==UPPER)?idx:(idx+1);
|
||||
draw_pin(os, "A1", gate->pin_DataA(i));
|
||||
draw_pin(os, "B1", gate->pin_DataB(i));
|
||||
if ( type == DOUBLE ) {
|
||||
draw_pin(os, "A1", gate->pin_DataA(idx+1));
|
||||
draw_pin(os, "B1", gate->pin_DataB(idx+1));
|
||||
}
|
||||
|
||||
// Carry input
|
||||
if ( type != FORCE0 && type != UPPER ) {
|
||||
os << " PIN, CIN, I, " << name_cout << "<" <<
|
||||
idx << ">" << endl;
|
||||
// All but FORCE0 cells have carry input
|
||||
if ( type != FORCE0 ) {
|
||||
os << " PIN, CIN, I, " << name_cout << "<" << idx << ">" << endl;
|
||||
}
|
||||
|
||||
// Connect the Cout0 to a signal so that I can connect
|
||||
// it to the adder.
|
||||
if ( type == LOWER || type == DOUBLE ) {
|
||||
switch (type) {
|
||||
case LOWER:
|
||||
case DOUBLE:
|
||||
os << " PIN, COUT0, O, " << name_cout << "<" << (idx+1) <<
|
||||
">" << endl;
|
||||
break;
|
||||
case EXAMINE_CI:
|
||||
case LOWER_W_CO:
|
||||
draw_pin(os, "COUT0", gate->pin_Cout());
|
||||
break;
|
||||
}
|
||||
|
||||
// Connect the Cout, this will connect to the next Cin
|
||||
if ( type == FORCE0 || type == UPPER || type == DOUBLE ) {
|
||||
if ( type == FORCE0 || type == DOUBLE ) {
|
||||
unsigned int to = (type==FORCE0)?(0):(idx+2);
|
||||
if (type==UPPER) to=idx+1;
|
||||
os << " PIN, COUT, O, " << name_cout << "<" << to <<
|
||||
">" << endl;
|
||||
}
|
||||
|
||||
// Carry In for mode UPPER comes from a strange place
|
||||
if ( type == UPPER ) {
|
||||
os << " PIN, A0, I, " << name_cout << "<dummy>" << endl;
|
||||
}
|
||||
|
||||
// These are the mode inputs from the CY_xx pseudo-device
|
||||
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
|
||||
os << " PIN, C" << cn << ", I, " << name << "/C"
|
||||
@@ -409,26 +418,24 @@ void target_xnf::draw_carry(ostream &os, const NetAddSub*gate, unsigned idx,
|
||||
}
|
||||
os << "END" << endl;
|
||||
|
||||
// Complete the dummy force used above
|
||||
if ( type == UPPER ) {
|
||||
os << "PWR, 0, " << name_cout << "<dummy>" << endl;
|
||||
}
|
||||
|
||||
// On to the CY_xx pseudo-device itself
|
||||
os << "SYM, " << name_cym << "<" << (idx) << ">, ";
|
||||
switch (type) {
|
||||
case FORCE0:
|
||||
case FORCE0:
|
||||
os << "CY4_37, CYMODE=FORCE-0" << endl;
|
||||
break;
|
||||
case LOWER:
|
||||
case LOWER:
|
||||
os << "CY4_01, CYMODE=ADD-F-CI" << endl;
|
||||
break;
|
||||
case UPPER:
|
||||
os << "CY4_03, CYMODE=ADD-G-F1" << endl;
|
||||
case LOWER_W_CO:
|
||||
os << "CY4_01, CYMODE=ADD-F-CI" << endl;
|
||||
break;
|
||||
case DOUBLE:
|
||||
case DOUBLE:
|
||||
os << "CY4_02, CYMODE=ADD-FG-CI" << endl;
|
||||
break;
|
||||
case EXAMINE_CI:
|
||||
os << "CY4_42, CYMODE-EXAMINE-CI" << endl;
|
||||
break;
|
||||
}
|
||||
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
|
||||
os << " PIN, C" << cn << ", O, " << name << "/C"
|
||||
@@ -454,32 +461,57 @@ void target_xnf::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
||||
{
|
||||
unsigned width = gate->width();
|
||||
|
||||
// Don't handle carry output yet
|
||||
// assert (count_outputs(gate->pin_Cout())==0);
|
||||
unsigned carry_width = width-1;
|
||||
|
||||
/* Make the force-0 cary mode object to initialize the bottom
|
||||
/* Make the force-0 carry mode object to initialize the bottom
|
||||
bits of the carry chain. Label this with the width instead
|
||||
of the bit position so that symbols don't clash. */
|
||||
if (carry_width%2) {
|
||||
draw_carry(os, gate, width, FORCE0);
|
||||
} else {
|
||||
draw_carry(os, gate, 0, UPPER);
|
||||
}
|
||||
|
||||
draw_carry(os, gate, width+1, FORCE0);
|
||||
|
||||
|
||||
/* Now make the 2 bit adders that chain from the cin
|
||||
initializer and up. Save the tail bit (if there is one) for
|
||||
later. */
|
||||
for (unsigned idx = 1-(carry_width%2) ; idx < carry_width-1 ; idx += 2) {
|
||||
initializer and up. Save the tail bits for later. */
|
||||
for (unsigned idx = 0 ; idx < width-2 ; idx += 2)
|
||||
draw_carry(os, gate, idx, DOUBLE);
|
||||
|
||||
/* Always have one or two tail bits. The situation gets a
|
||||
little tricky if we want the carry output, so handle that
|
||||
here.
|
||||
|
||||
If the carry-out is connected, and there are an even number
|
||||
of data bits, we need to see the cout from the CLB. This is
|
||||
done by configuring the top CLB CY device as ADD-FG-CI (to
|
||||
activate cout) and create an extra CLB CY device on top of
|
||||
the carry chain configured EXAMINE-CI to put the carry into
|
||||
the G function block.
|
||||
|
||||
IF the carry-out is connected and there are an odd number
|
||||
of data bits, then the top CLB can be configured to carry
|
||||
the top bit in the F unit and deliver the carry out through
|
||||
the G unit.
|
||||
|
||||
If the carry-out is not connected, then configure this top
|
||||
CLB as ADD-F-CI. The draw_xor for the top bit will include
|
||||
the F carry if needed. */
|
||||
|
||||
if (gate->pin_Cout().is_linked()) {
|
||||
if (width%2 == 0) {
|
||||
draw_carry(os, gate, width-2, DOUBLE);
|
||||
draw_carry(os, gate, width, EXAMINE_CI);
|
||||
} else {
|
||||
draw_carry(os, gate, width-1, LOWER_W_CO);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (width%2 == 0)
|
||||
draw_carry(os, gate, width-2, LOWER);
|
||||
else
|
||||
draw_carry(os, gate, width-1, LOWER);
|
||||
}
|
||||
|
||||
/* Always have a tail bit */
|
||||
draw_carry(os, gate, carry_width-1, LOWER);
|
||||
|
||||
for (unsigned idx = 0 ; idx < width ; ++idx) {
|
||||
/* Now draw all the single bit (plus carry in) adders from XOR
|
||||
gates. This puts the F and G units to use. */
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
draw_xor(os, gate, idx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -545,17 +577,43 @@ void target_xnf::lpm_mux(ostream&os, const NetMux*net)
|
||||
|
||||
}
|
||||
|
||||
void target_xnf::lpm_ram_dq(ostream&os, const NetRamDq*ram)
|
||||
{
|
||||
assert(ram->count_partners() == 1);
|
||||
|
||||
const NetMemory*mem = ram->mem();
|
||||
|
||||
for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) {
|
||||
os << "SYM, " << mangle(ram->name())
|
||||
<< "<" << idx << ">, RAMS" << endl;
|
||||
|
||||
draw_pin(os, "O", ram->pin_Q(idx));
|
||||
draw_pin(os, "D", ram->pin_Data(idx));
|
||||
draw_pin(os, "WE", ram->pin_WE());
|
||||
draw_pin(os, "WCLK", ram->pin_InClock());
|
||||
for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) {
|
||||
strstream tmp;
|
||||
tmp << "A" << adr << ends;
|
||||
draw_pin(os, tmp.str(), ram->pin_Address(adr));
|
||||
}
|
||||
|
||||
os << "END" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void target_xnf::net_const(ostream&os, const NetConst*c)
|
||||
{
|
||||
verinum::V v=c->value();
|
||||
assert(v==verinum::V0 || v==verinum::V1);
|
||||
const NetObj::Link& lnk = c->pin(0);
|
||||
// Code parallels draw_pin above, some smart c++ guru should
|
||||
// find a way to make a method out of this.
|
||||
unsigned cpin;
|
||||
const NetObj*cur;
|
||||
for (unsigned idx = 0 ; idx < c->pin_count() ; idx += 1) {
|
||||
verinum::V v=c->value(idx);
|
||||
assert(v==verinum::V0 || v==verinum::V1);
|
||||
const NetObj::Link& lnk = c->pin(idx);
|
||||
// Code parallels draw_pin above, some smart c++ guru should
|
||||
// find a way to make a method out of this.
|
||||
unsigned cpin;
|
||||
const NetObj*cur;
|
||||
|
||||
os << " PWR, " << v << ", " << choose_sig_name(&lnk) << endl;
|
||||
os << " PWR, " << v << ", " << choose_sig_name(&lnk) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -653,6 +711,21 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-xnf.cc,v $
|
||||
* Revision 1.23 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.22 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.21 1999/12/16 18:54:32 steve
|
||||
* Capture the carry out of carry-chain addition.
|
||||
*
|
||||
* Revision 1.20 1999/12/16 02:42:15 steve
|
||||
* Simulate carry output on adders.
|
||||
*
|
||||
* Revision 1.19 1999/12/05 19:30:43 steve
|
||||
* Generate XNF RAMS from synthesized memories.
|
||||
*
|
||||
* Revision 1.18 1999/11/19 03:02:25 steve
|
||||
* Detect flip-flops connected to opads and turn
|
||||
* them into OUTFF devices. Inprove support for
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: target.cc,v 1.28 1999/11/28 23:42:03 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: target.cc,v 1.30 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -97,6 +97,12 @@ void target_t::lpm_ff(ostream&, const NetFF*)
|
||||
"Unhandled NetFF." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_mult(ostream&, const NetMult*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetMult." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_mux(ostream&, const NetMux*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -308,6 +314,12 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.30 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.29 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.28 1999/11/28 23:42:03 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: target.h,v 1.27 1999/11/28 23:42:03 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: target.h,v 1.29 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -74,6 +74,7 @@ struct target_t {
|
||||
virtual void lpm_clshift(ostream&os, const NetCLShift*);
|
||||
virtual void lpm_compare(ostream&os, const NetCompare*);
|
||||
virtual void lpm_ff(ostream&os, const NetFF*);
|
||||
virtual void lpm_mult(ostream&os, const NetMult*);
|
||||
virtual void lpm_mux(ostream&os, const NetMux*);
|
||||
virtual void lpm_ram_dq(ostream&os, const NetRamDq*);
|
||||
|
||||
@@ -146,6 +147,12 @@ extern const struct target *target_table[];
|
||||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.29 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.28 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.27 1999/11/28 23:42:03 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: targets.cc,v 1.4 1999/05/01 02:57:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: targets.cc,v 1.5 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -37,6 +37,9 @@ const struct target *target_table[] = {
|
||||
|
||||
/*
|
||||
* $Log: targets.cc,v $
|
||||
* Revision 1.5 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 1999/05/01 02:57:53 steve
|
||||
* Handle much more complex event expressions.
|
||||
*
|
||||
|
||||
@@ -31,6 +31,8 @@ Defines macro \fImacro\fP as \fIdefn\fP.
|
||||
.B -I\fIincludepath\fP
|
||||
Append path \fIincludepath\fP to list of paths searched for include files.
|
||||
.TP 8
|
||||
.B -m\fImodule\fP
|
||||
Add this module to the list of modules to be loaded by the simulation.
|
||||
.B -X
|
||||
Generate XNF files as output. Default is VVM-format.
|
||||
.TP 8
|
||||
|
||||
+4
-3
@@ -21,7 +21,7 @@
|
||||
# Added support for functors, especially for the XNF target. <[email protected]>
|
||||
|
||||
# Setup variables
|
||||
execPath=@bindir@
|
||||
execPath=@libdir@/ivl
|
||||
execIVLPP=${execPath}/ivlpp
|
||||
execIVL=${execPath}/ivl
|
||||
execCpp=@CXX@
|
||||
@@ -46,7 +46,7 @@ flags=""
|
||||
#fi
|
||||
|
||||
# Try to extract given parameters
|
||||
parameter=`getopt D:I:Xxf:o:s:t: "$@"`
|
||||
parameter=`getopt D:I:Xxf:m:o:s:t: "$@"`
|
||||
eval set -- "${parameter}"
|
||||
while true ; do
|
||||
|
||||
@@ -55,6 +55,7 @@ while true ; do
|
||||
-I) extIncPath="${extIncPath} -I $2" ; shift 2 ;;
|
||||
-X) target="xnf" ; shift ;;
|
||||
-f) flags="$flags -f$2" ; shift 2 ;;
|
||||
-m) flags="$flags -m$2" ; shift 2 ;;
|
||||
-o) outputFile=$2 ; shift 2 ;;
|
||||
-s) topModule="-s $2 " ; shift 2 ;;
|
||||
-t) target="$2" ; shift 2 ;;
|
||||
@@ -115,7 +116,7 @@ case "${target}" in
|
||||
|
||||
"xnf") mv ${tmpCCFile} ${outputFile} ;;
|
||||
|
||||
"vvm") ${execCpp} -rdynamic -I${includedir} -L${libdir} ${tmpCCFile} -o ${outputFile} -lvvm -ldl ;
|
||||
"vvm") ${execCpp} -rdynamic -I${includedir} -L${libdir} ${tmpCCFile} -o ${outputFile} -lvvm @dllib@ ;
|
||||
if test $? -ne 0 ; then
|
||||
echo "C++ compilation failed. Terminating compilation."
|
||||
rm -f ${tmpCCFile}
|
||||
|
||||
+28
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: verinum.cc,v 1.12 1999/11/06 16:00:17 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verinum.cc,v 1.16 2000/02/23 04:43:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "verinum.h"
|
||||
@@ -25,12 +25,12 @@
|
||||
# include <cassert>
|
||||
|
||||
verinum::verinum()
|
||||
: bits_(0), nbits_(0), has_len_(false), string_flag_(false)
|
||||
: bits_(0), nbits_(0), has_len_(false), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
}
|
||||
|
||||
verinum::verinum(const V*bits, unsigned nbits, bool has_len)
|
||||
: has_len_(has_len), string_flag_(false)
|
||||
: has_len_(has_len), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
nbits_ = nbits;
|
||||
bits_ = new V [nbits];
|
||||
@@ -40,7 +40,7 @@ verinum::verinum(const V*bits, unsigned nbits, bool has_len)
|
||||
}
|
||||
|
||||
verinum::verinum(const string&str)
|
||||
: has_len_(true), string_flag_(true)
|
||||
: has_len_(true), has_sign_(false), string_flag_(true)
|
||||
{
|
||||
nbits_ = str.length() * 8;
|
||||
bits_ = new V [nbits_];
|
||||
@@ -61,7 +61,7 @@ verinum::verinum(const string&str)
|
||||
}
|
||||
|
||||
verinum::verinum(verinum::V val, unsigned n)
|
||||
: has_len_(true), string_flag_(false)
|
||||
: has_len_(true), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
nbits_ = n;
|
||||
bits_ = new V[nbits_];
|
||||
@@ -70,7 +70,7 @@ verinum::verinum(verinum::V val, unsigned n)
|
||||
}
|
||||
|
||||
verinum::verinum(unsigned long val, unsigned n)
|
||||
: has_len_(true), string_flag_(false)
|
||||
: has_len_(true), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
nbits_ = n;
|
||||
bits_ = new V[nbits_];
|
||||
@@ -86,6 +86,7 @@ verinum::verinum(const verinum&that)
|
||||
nbits_ = that.nbits_;
|
||||
bits_ = new V[nbits_];
|
||||
has_len_ = that.has_len_;
|
||||
has_sign_ = that.has_sign_;
|
||||
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1)
|
||||
bits_[idx] = that.bits_[idx];
|
||||
}
|
||||
@@ -97,6 +98,7 @@ verinum::verinum(const verinum&that, unsigned nbits)
|
||||
nbits_ = nbits;
|
||||
bits_ = new V[nbits_];
|
||||
has_len_ = true;
|
||||
has_sign_ = false;
|
||||
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1)
|
||||
bits_[idx] = that.bits_[idx];
|
||||
}
|
||||
@@ -116,6 +118,7 @@ verinum& verinum::operator= (const verinum&that)
|
||||
bits_[idx] = that.bits_[idx];
|
||||
|
||||
has_len_ = that.has_len_;
|
||||
has_sign_ = that.has_sign_;
|
||||
string_flag_ = that.string_flag_;
|
||||
return *this;
|
||||
}
|
||||
@@ -164,8 +167,9 @@ signed long verinum::as_long() const
|
||||
|
||||
signed long val = 0;
|
||||
|
||||
// Extend the sign bit to fill the long.
|
||||
if (bits_[nbits_-1] == V1)
|
||||
// Extend the sign bit to fill the long. (But only for signed
|
||||
// numbers.)
|
||||
if (has_sign_ && (bits_[nbits_-1] == V1))
|
||||
val = -1;
|
||||
|
||||
for (unsigned idx = nbits_ ; idx > 0 ; idx -= 1) {
|
||||
@@ -391,7 +395,7 @@ static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c)
|
||||
return verinum::V0;
|
||||
}
|
||||
|
||||
verinum not(const verinum&left)
|
||||
verinum v_not(const verinum&left)
|
||||
{
|
||||
verinum val = left;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
@@ -441,7 +445,7 @@ verinum operator + (const verinum&left, const verinum&right)
|
||||
|
||||
verinum operator - (const verinum&left, const verinum&r)
|
||||
{
|
||||
verinum right = not(r);
|
||||
verinum right = v_not(r);
|
||||
unsigned min = left.len();
|
||||
if (right.len() < min) min = right.len();
|
||||
|
||||
@@ -467,6 +471,18 @@ verinum operator - (const verinum&left, const verinum&r)
|
||||
|
||||
/*
|
||||
* $Log: verinum.cc,v $
|
||||
* Revision 1.16 2000/02/23 04:43:43 steve
|
||||
* Some compilers do not accept the not symbol.
|
||||
*
|
||||
* Revision 1.15 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.14 2000/01/07 03:45:49 steve
|
||||
* Initial support for signed constants.
|
||||
*
|
||||
* Revision 1.13 2000/01/06 05:57:06 steve
|
||||
* Only sign-extend unsized numbers.
|
||||
*
|
||||
* Revision 1.12 1999/11/06 16:00:17 steve
|
||||
* Put number constants into a static table.
|
||||
*
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: verinum.h,v 1.8 1999/11/06 16:00:17 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verinum.h,v 1.11 2000/02/23 04:43:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -56,6 +56,9 @@ class verinum {
|
||||
// in some way.
|
||||
bool has_len() const { return has_len_; }
|
||||
|
||||
bool has_sign(bool flag) { has_sign_ = flag; return has_sign_; }
|
||||
bool has_sign() const { return has_sign_; }
|
||||
|
||||
// A number is "defined" if there are no x or z bits in its value.
|
||||
bool is_defined() const;
|
||||
|
||||
@@ -82,6 +85,7 @@ class verinum {
|
||||
V* bits_;
|
||||
unsigned nbits_;
|
||||
bool has_len_;
|
||||
bool has_sign_;
|
||||
|
||||
// These are some convenience flags that help us do a better
|
||||
// job of pretty-printing values.
|
||||
@@ -98,8 +102,19 @@ extern verinum::V operator <= (const verinum&left, const verinum&right);
|
||||
extern verinum operator + (const verinum&left, const verinum&right);
|
||||
extern verinum operator - (const verinum&left, const verinum&right);
|
||||
|
||||
extern verinum v_not(const verinum&left);
|
||||
|
||||
/*
|
||||
* $Log: verinum.h,v $
|
||||
* Revision 1.11 2000/02/23 04:43:43 steve
|
||||
* Some compilers do not accept the not symbol.
|
||||
*
|
||||
* Revision 1.10 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/07 03:45:49 steve
|
||||
* Initial support for signed constants.
|
||||
*
|
||||
* Revision 1.8 1999/11/06 16:00:17 steve
|
||||
* Put number constants into a static table.
|
||||
*
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: verireal.cc,v 1.1 1999/06/15 02:50:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verireal.cc,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "verireal.h"
|
||||
@@ -92,6 +92,9 @@ verireal::~verireal()
|
||||
|
||||
/*
|
||||
* $Log: verireal.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/06/15 02:50:02 steve
|
||||
* Add lexical support for real numbers.
|
||||
*
|
||||
|
||||
+5
-2
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: verireal.h,v 1.1 1999/06/15 02:50:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verireal.h,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
class verireal {
|
||||
@@ -37,6 +37,9 @@ class verireal {
|
||||
|
||||
/*
|
||||
* $Log: verireal.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/06/15 02:50:02 steve
|
||||
* Add lexical support for real numbers.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
Makefile
|
||||
sys_readmem_lex.c
|
||||
system.vpi
|
||||
dep
|
||||
|
||||
+7
-3
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.7 1999/11/07 20:33:30 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.9 2000/01/23 23:54:36 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -52,11 +52,15 @@ all: system.vpi
|
||||
$(CC) -Wall $(CPPFLAGS) -I$(srcdir) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = sys_table.o sys_display.o sys_finish.o sys_vcd.o
|
||||
O = sys_table.o sys_display.o sys_finish.o sys_readmem.o sys_readmem_lex.o \
|
||||
sys_vcd.o
|
||||
|
||||
system.vpi: $O
|
||||
$(CC) -shared -o $@ $O
|
||||
|
||||
sys_readmem_lex.c: sys_readmem_lex.lex
|
||||
flex -t -Preadmem sys_readmem_lex.lex > sys_readmem_lex.c
|
||||
|
||||
clean:
|
||||
rm -f *.o dep/*.d
|
||||
|
||||
@@ -64,7 +68,7 @@ install: all installdirs $(libdir)/ivl/system.vpi \
|
||||
$(includedir)/vpi_user.h
|
||||
|
||||
$(libdir)/ivl/system.vpi: ./system.vpi
|
||||
$(INSTALL_PROGRAM) ./system.vpi $(libdir)/ivl/system.vpi
|
||||
$(INSTALL_DATA) ./system.vpi $(libdir)/ivl/system.vpi
|
||||
|
||||
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
|
||||
|
||||
+9
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: sys_display.c,v 1.9 1999/11/07 02:25:07 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_display.c,v 1.11 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
@@ -188,6 +188,7 @@ static void do_display(struct strobe_cb_info*info)
|
||||
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
case vpiMemoryWord:
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(item, &value);
|
||||
vpi_printf("%s", value.value.str);
|
||||
@@ -412,6 +413,12 @@ void sys_display_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_display.c,v $
|
||||
* Revision 1.11 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.10 2000/02/13 19:18:27 steve
|
||||
* Accept memory words as parameter to $display.
|
||||
*
|
||||
* Revision 1.9 1999/11/07 02:25:07 steve
|
||||
* Add the $monitor implementation.
|
||||
*
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: sys_finish.c,v 1.3 1999/08/28 02:10:44 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_finish.c,v 1.4 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
@@ -42,6 +42,9 @@ void sys_finish_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_finish.c,v $
|
||||
* Revision 1.4 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/08/28 02:10:44 steve
|
||||
* Call the right vpiFinish code.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 1999 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: sys_readmem.c,v 1.5 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <assert.h>
|
||||
# include "sys_readmem_lex.h"
|
||||
|
||||
static int sys_readmem_calltf(char*name)
|
||||
{
|
||||
int code;
|
||||
int wwid;
|
||||
char*path;
|
||||
FILE*file;
|
||||
s_vpi_value value;
|
||||
vpiHandle words;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: file name parameter missing.\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiType, item) != vpiConstant) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiConstType, item) != vpiStringConst) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(item, &value);
|
||||
path = strdup(value.value.str);
|
||||
|
||||
/* Get and check the second paramter. It must be a memory. */
|
||||
item = vpi_scan(argv);
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: Missing memory parameter\n", name);
|
||||
free(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiType, item) != vpiMemory) {
|
||||
vpi_printf("%s: Second parameter must be a memory.\n", name);
|
||||
free(path);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXXX remaining parameters not supported. */
|
||||
vpi_free_object(argv);
|
||||
|
||||
/* Open the data file. */
|
||||
file = fopen(path, "r");
|
||||
if (file == 0) {
|
||||
vpi_printf("%s: Unable to open %s for reading.\n", name, path);
|
||||
free(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
words = vpi_iterate(vpiMemoryWord, item);
|
||||
assert(words);
|
||||
|
||||
item = vpi_scan(words);
|
||||
wwid = vpi_get(vpiSize, item);
|
||||
|
||||
value.format = vpiVectorVal;
|
||||
value.value.vector = calloc((wwid+31)/32, sizeof (s_vpi_vecval));
|
||||
if (strcmp(name,"$readmemb") == 0)
|
||||
sys_readmem_start_file(file, 1, wwid, value.value.vector);
|
||||
else
|
||||
sys_readmem_start_file(file, 0, wwid, value.value.vector);
|
||||
|
||||
while (item && ((code = readmemlex()) != 0)) {
|
||||
switch (code) {
|
||||
case MEM_ADDRESS:
|
||||
vpi_printf("XXXX addresses not supported\n");
|
||||
break;
|
||||
case MEM_WORD:
|
||||
vpi_put_value(item, &value, 0, vpiNoDelay);
|
||||
item = vpi_scan(words);
|
||||
break;
|
||||
default:
|
||||
vpi_printf("Huh?! (%d)\n", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item) vpi_free_object(words);
|
||||
free(value.value.vector);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_readmem_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$readmemh";
|
||||
tf_data.calltf = sys_readmem_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$readmemh";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$readmemb";
|
||||
tf_data.calltf = sys_readmem_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$readmemb";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sys_readmem.c,v $
|
||||
* Revision 1.5 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 2000/01/23 23:54:36 steve
|
||||
* Compile time problems with vpi_user.h
|
||||
*
|
||||
* Revision 1.3 1999/12/15 04:35:34 steve
|
||||
* Add readmemb.
|
||||
*
|
||||
* Revision 1.2 1999/12/15 04:02:38 steve
|
||||
* Excess warning.
|
||||
*
|
||||
* Revision 1.1 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef __sys_readmem_lex_H
|
||||
#define __sys_readmem_lex_H
|
||||
/*
|
||||
* Copyright (c) 1999 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)
|
||||
#ident "$Id: sys_readmem_lex.h,v 1.2 2000/01/23 23:54:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
# include "vpi_user.h"
|
||||
|
||||
# define MEM_ADDRESS 257
|
||||
# define MEM_WORD 258
|
||||
|
||||
extern void sys_readmem_start_file(FILE*in, int bin_flag,
|
||||
unsigned width, struct t_vpi_vecval*val);
|
||||
extern int readmemlex();
|
||||
|
||||
/*
|
||||
* $Log: sys_readmem_lex.h,v $
|
||||
* Revision 1.2 2000/01/23 23:54:36 steve
|
||||
* Compile time problems with vpi_user.h
|
||||
*
|
||||
* Revision 1.1 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* 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: sys_readmem_lex.lex,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
# include "sys_readmem_lex.h"
|
||||
# include <string.h>
|
||||
static void make_hex_value();
|
||||
static void make_bin_value();
|
||||
%}
|
||||
|
||||
%x BIN
|
||||
%x HEX
|
||||
|
||||
%option noyywrap
|
||||
%%
|
||||
|
||||
<*>"//".* { ; }
|
||||
<*>[ \t\f\n\r] { ; }
|
||||
|
||||
<*>@[0-9a-fA-F]+ { return MEM_ADDRESS; }
|
||||
<HEX>[0-9a-fA-FxXzZ_]+ { make_hex_value(); return MEM_WORD; }
|
||||
<BIN>[01_]+ { make_bin_value(); return MEM_WORD; }
|
||||
|
||||
%%
|
||||
static unsigned word_width = 0;
|
||||
static struct t_vpi_vecval*vecval = 0;
|
||||
|
||||
static void make_hex_value()
|
||||
{
|
||||
char*beg = yytext;
|
||||
char*end = beg + strlen(beg);
|
||||
struct t_vpi_vecval*cur;
|
||||
int idx;
|
||||
int width = 0, word_max = word_width;
|
||||
|
||||
for (idx = 0, cur = vecval ; idx < word_max ; idx += 32, cur += 1) {
|
||||
cur->aval = 0;
|
||||
cur->bval = 0;
|
||||
}
|
||||
|
||||
cur = vecval;
|
||||
while ((width < word_max) && (end > beg)) {
|
||||
int aval, bval;
|
||||
|
||||
end -= 1;
|
||||
if (*end == '_') continue;
|
||||
switch (*end) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
aval = *end - '0';
|
||||
bval = 0;
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
aval = *end - 'a' + 10;
|
||||
bval = 0;
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
aval = *end - 'A' + 10;
|
||||
bval = 0;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
aval = 15;
|
||||
bval = 15;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
aval = 0;
|
||||
bval = 15;
|
||||
break;
|
||||
}
|
||||
|
||||
cur->aval |= aval << width;
|
||||
cur->bval |= bval << width;
|
||||
width += 4;
|
||||
if (width == 32) {
|
||||
cur += 1;
|
||||
width = 0;
|
||||
word_max -= 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void make_bin_value()
|
||||
{
|
||||
char*beg = yytext;
|
||||
char*end = beg + strlen(beg);
|
||||
struct t_vpi_vecval*cur;
|
||||
int idx;
|
||||
int width = 0, word_max = word_width;
|
||||
|
||||
for (idx = 0, cur = vecval ; idx < word_max ; idx += 32, cur += 1) {
|
||||
cur->aval = 0;
|
||||
cur->bval = 0;
|
||||
}
|
||||
|
||||
cur = vecval;
|
||||
while ((width < word_max) && (end > beg)) {
|
||||
int aval, bval;
|
||||
|
||||
end -= 1;
|
||||
if (*end == '_') continue;
|
||||
switch (*end) {
|
||||
case '0':
|
||||
case '1':
|
||||
aval = *end - '0';
|
||||
bval = 0;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
aval = 1;
|
||||
bval = 1;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
aval = 0;
|
||||
bval = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
cur->aval |= aval << width;
|
||||
cur->bval |= bval << width;
|
||||
width += 1;
|
||||
if (width == 32) {
|
||||
cur += 1;
|
||||
width = 0;
|
||||
word_max -= 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sys_readmem_start_file(FILE*in, int bin_flag,
|
||||
unsigned width, struct t_vpi_vecval *vv)
|
||||
{
|
||||
yyin = in;
|
||||
YY_FLUSH_BUFFER;
|
||||
BEGIN(bin_flag? BIN : HEX);
|
||||
word_width = width;
|
||||
vecval = vv;
|
||||
}
|
||||
+10
-2
@@ -16,17 +16,19 @@
|
||||
* 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)
|
||||
#ident "$Id: sys_table.c,v 1.2 1999/11/07 20:33:30 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_table.c,v 1.4 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
extern void sys_finish_register();
|
||||
extern void sys_display_register();
|
||||
extern void sys_readmem_register();
|
||||
extern void sys_vcd_register();
|
||||
|
||||
void (*vlog_startup_routines[])() = {
|
||||
sys_finish_register,
|
||||
sys_display_register,
|
||||
sys_readmem_register,
|
||||
sys_vcd_register,
|
||||
0
|
||||
};
|
||||
@@ -34,6 +36,12 @@ void (*vlog_startup_routines[])() = {
|
||||
|
||||
/*
|
||||
* $Log: sys_table.c,v $
|
||||
* Revision 1.4 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.2 1999/11/07 20:33:30 steve
|
||||
* Add VCD output and related system tasks.
|
||||
*
|
||||
|
||||
+69
-22
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: sys_vcd.c,v 1.2 1999/11/28 00:56:08 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_vcd.c,v 1.7 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -25,7 +25,7 @@
|
||||
* funcitons.
|
||||
*/
|
||||
|
||||
# include <vpi_user.h>
|
||||
# include "vpi_user.h"
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
@@ -44,10 +44,36 @@ struct vcd_info {
|
||||
static struct vcd_info*vcd_list = 0;
|
||||
unsigned long vcd_cur_time = 0;
|
||||
|
||||
static void show_this_item(struct vcd_info*info)
|
||||
{
|
||||
s_vpi_value value;
|
||||
|
||||
if (vpi_get(vpiSize, info->item) == 1) {
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(info->item, &value);
|
||||
fprintf(dump_file, "%s%s\n", value.value.str, info->ident);
|
||||
} else {
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(info->item, &value);
|
||||
fprintf(dump_file, "b%s %s\n", value.value.str, info->ident);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function writes out all the traced variables, whether they
|
||||
* changed or not.
|
||||
*/
|
||||
static void vcd_checkpoint()
|
||||
{
|
||||
struct vcd_info*cur;
|
||||
|
||||
for (cur = vcd_list ; cur ; cur = cur->next)
|
||||
show_this_item(cur);
|
||||
}
|
||||
|
||||
static int variable_cb(p_cb_data cause)
|
||||
{
|
||||
unsigned long now = cause->time->low;
|
||||
s_vpi_value value;
|
||||
struct t_cb_data cb;
|
||||
struct vcd_info*info = (struct vcd_info*)cause->user_data;
|
||||
|
||||
@@ -61,21 +87,19 @@ static int variable_cb(p_cb_data cause)
|
||||
vcd_cur_time = now;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiSize, info->item) == 1) {
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(info->item, &value);
|
||||
fprintf(dump_file, "%s%s\n", value.value.str, info->ident);
|
||||
} else {
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(info->item, &value);
|
||||
fprintf(dump_file, "b%s %s\n", value.value.str, info->ident);
|
||||
}
|
||||
show_this_item(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_dumpall_calltf(char*name)
|
||||
{
|
||||
s_vpi_time now;
|
||||
vpi_get_time(0, &now);
|
||||
fprintf(dump_file, "#%u\n", now.low);
|
||||
vcd_cur_time = now.low;
|
||||
vcd_checkpoint();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -85,9 +109,9 @@ static int sys_dumpfile_calltf(char*name)
|
||||
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
|
||||
if (item) {
|
||||
if (argv) {
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
s_vpi_value value;
|
||||
|
||||
if (vpi_get(vpiType, item) != vpiConstant) {
|
||||
@@ -122,12 +146,11 @@ static int sys_dumpfile_calltf(char*name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scan_scope(unsigned depth, vpiHandle argv)
|
||||
static unsigned scan_scope(unsigned depth, vpiHandle argv, unsigned nident)
|
||||
{
|
||||
struct t_cb_data cb;
|
||||
struct vcd_info*info;
|
||||
char ident[64];
|
||||
unsigned nident = 0;
|
||||
|
||||
vpiHandle item;
|
||||
vpiHandle sublist;
|
||||
@@ -164,7 +187,7 @@ static void scan_scope(unsigned depth, vpiHandle argv)
|
||||
case vpiModule:
|
||||
sublist = vpi_iterate(vpiInternalScope, item);
|
||||
if (sublist && (depth > 0))
|
||||
scan_scope(depth-1, sublist);
|
||||
nident = scan_scope(depth-1, sublist, nident);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -172,25 +195,34 @@ static void scan_scope(unsigned depth, vpiHandle argv)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nident;
|
||||
}
|
||||
|
||||
static int sys_dumpvars_calltf(char*name)
|
||||
{
|
||||
s_vpi_time now;
|
||||
vpiHandle item;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
|
||||
if (item == 0) {
|
||||
if (argv == 0) {
|
||||
vpi_printf("SORRY: %s requires arguments\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = vpi_scan(argv);
|
||||
|
||||
assert(dump_file);
|
||||
|
||||
scan_scope(99, argv);
|
||||
scan_scope(99, argv, 0);
|
||||
|
||||
fprintf(dump_file, "$enddefinitions $end\n");
|
||||
fprintf(dump_file, "#0\n");
|
||||
|
||||
vpi_get_time(0, &now);
|
||||
fprintf(dump_file, "#%u\n", now.low);
|
||||
|
||||
vcd_checkpoint();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -226,6 +258,21 @@ void sys_vcd_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_vcd.c,v $
|
||||
* Revision 1.7 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 2000/02/17 06:04:30 steve
|
||||
* Fix overlap of identifiers when multiple modules used.
|
||||
*
|
||||
* Revision 1.5 2000/01/23 23:54:36 steve
|
||||
* Compile time problems with vpi_user.h
|
||||
*
|
||||
* Revision 1.4 2000/01/20 06:04:55 steve
|
||||
* $dumpall checkpointing in VCD dump.
|
||||
*
|
||||
* Revision 1.3 2000/01/13 04:48:50 steve
|
||||
* Catch some parameter problems.
|
||||
*
|
||||
* Revision 1.2 1999/11/28 00:56:08 steve
|
||||
* Build up the lists in the scope of a module,
|
||||
* and get $dumpvars to scan the scope for items.
|
||||
|
||||
+31
-2
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_user.h,v 1.9 1999/11/28 00:56:08 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_user.h,v 1.13 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -59,6 +59,10 @@ typedef struct t_vpi_time {
|
||||
#define vpiSimTime 2
|
||||
#define vpiSuppressTime 3
|
||||
|
||||
typedef struct t_vpi_vecval {
|
||||
int aval, bval; /* ab encoding: 00=0, 10=1, 11=X, 01=Z */
|
||||
} s_vpi_vecval, *p_vpi_vecval;
|
||||
|
||||
/*
|
||||
* This structure holds values that are passed back and forth between
|
||||
* the simulator and the application.
|
||||
@@ -124,6 +128,15 @@ typedef struct t_vpi_value {
|
||||
# define vpiHexConst 5
|
||||
# define vpiStringConst 6
|
||||
|
||||
/* DELAY MODES */
|
||||
#define vpiNoDelay 1
|
||||
#define vpiInertialDelay 2
|
||||
#define vpiTransportDelay 3
|
||||
#define vpiPureTransportDelay 4
|
||||
|
||||
#define vpiForceFlag 5
|
||||
#define vpiReleaseFlag 6
|
||||
|
||||
|
||||
/* VPI FUNCTIONS */
|
||||
extern void vpi_register_systf(const struct t_vpi_systf_data*ss);
|
||||
@@ -194,10 +207,14 @@ extern void vpi_sim_control(int operation, ...);
|
||||
extern vpiHandle vpi_handle(int type, vpiHandle ref);
|
||||
extern vpiHandle vpi_iterate(int type, vpiHandle ref);
|
||||
extern vpiHandle vpi_scan(vpiHandle iter);
|
||||
extern vpiHandle vpi_handle_by_index(vpiHandle ref, int index);
|
||||
|
||||
extern void vpi_get_time(vpiHandle obj, s_vpi_time*t);
|
||||
extern int vpi_get(int property, vpiHandle ref);
|
||||
extern char* vpi_get_str(int property, vpiHandle ref);
|
||||
extern void vpi_get_value(vpiHandle expr, p_vpi_value value);
|
||||
extern vpiHandle vpi_put_value(vpiHandle obj, p_vpi_value value,
|
||||
p_vpi_time when, int flags);
|
||||
|
||||
extern int vpi_free_object(vpiHandle ref);
|
||||
|
||||
@@ -211,6 +228,18 @@ extern void (*vlog_startup_routines[])();
|
||||
|
||||
/*
|
||||
* $Log: vpi_user.h,v $
|
||||
* Revision 1.13 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.12 2000/02/13 19:18:28 steve
|
||||
* Accept memory words as parameter to $display.
|
||||
*
|
||||
* Revision 1.11 2000/01/20 06:04:55 steve
|
||||
* $dumpall checkpointing in VCD dump.
|
||||
*
|
||||
* Revision 1.10 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.9 1999/11/28 00:56:08 steve
|
||||
* Build up the lists in the scope of a module,
|
||||
* and get $dumpvars to scan the scope for items.
|
||||
|
||||
@@ -9,12 +9,12 @@ useful for batch simulation.
|
||||
|
||||
Although none are required, these processing steps are recommended:
|
||||
nobufz
|
||||
sigfold
|
||||
nodangle
|
||||
propinit
|
||||
|
||||
So a sample command line to compile a Verilog file to C++ would be:
|
||||
|
||||
ivl -F nobufz -F sigfold -F propinit -t vvm -o foo.cc foo.vl
|
||||
ivl -F nobufz -F nodangle -F propinit -t vvm -o foo.cc foo.vl
|
||||
|
||||
Once the program is compiled down to C++ code, it needs to be further
|
||||
compiled and linked into an executable image. The command for doing
|
||||
@@ -110,8 +110,11 @@ bits are at:
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
$Id: vvm.txt,v 1.3 1999/08/18 03:45:36 steve Exp $
|
||||
$Id: vvm.txt,v 1.4 1999/12/30 17:37:14 steve Exp $
|
||||
$Log: vvm.txt,v $
|
||||
Revision 1.4 1999/12/30 17:37:14 steve
|
||||
Remove the now useless sigfold functor.
|
||||
|
||||
Revision 1.3 1999/08/18 03:45:36 steve
|
||||
Update compile command line.
|
||||
|
||||
|
||||
+7
-7
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.14 1999/11/27 19:07:58 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.19 2000/02/13 19:18:28 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -50,16 +50,16 @@ all: libvvm.a
|
||||
|
||||
%.o dep/%.d: %.cc
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CXX) -Wall -fno-exceptions $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
$(CXX) -Wall -fno-exceptions $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
%.o dep/%.d: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CFLAGS) -MD -c $< -o $*.o
|
||||
$(CC) -Wall $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = vvm_bit.o vvm_calltf.o vvm_event.o vvm_gates.o vvm_pevent.o \
|
||||
vvm_simulation.o vvm_thread.o vpip.o
|
||||
O = vvm_bit.o vvm_calltf.o vvm_event.o vvm_gates.o vvm_mult.o \
|
||||
vvm_pevent.o vvm_thread.o vpip.o
|
||||
|
||||
P = vpi_callback.o \
|
||||
vpi_const.o vpi_iter.o vpi_memory.o vpi_null.o \
|
||||
@@ -84,7 +84,7 @@ install: all installdirs $(libdir)/libvvm.a \
|
||||
$(includedir)/vvm_calltf.h
|
||||
|
||||
$(libdir)/libvvm.a: ./libvvm.a
|
||||
$(INSTALL_PROGRAM) ./libvvm.a $(libdir)/libvvm.a
|
||||
$(INSTALL_DATA) ./libvvm.a $(libdir)/libvvm.a
|
||||
|
||||
$(includedir)/vvm.h: $(srcdir)/vvm.h
|
||||
$(INSTALL_DATA) $(srcdir)/vvm.h $(includedir)/vvm.h
|
||||
@@ -117,4 +117,4 @@ uninstall:
|
||||
rm -f $(includedir)/vpi_priv.h
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
-include $(patsubst %.o, dep/%.d, $O $P)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef __vvm_machine_H
|
||||
#define __vvm_machine_H
|
||||
/*
|
||||
* 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: machine.h,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef NEED_LU
|
||||
#define LU "_"
|
||||
#else
|
||||
#define LU ""
|
||||
#endif
|
||||
|
||||
#ifdef NEED_TU
|
||||
#define TU "_"
|
||||
#else
|
||||
#define TU ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: machine.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 2000/01/24 00:18:20 steve
|
||||
* Handle systems that need underscores in symbols.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+9
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_callback.c,v 1.4 1999/11/07 20:33:30 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_callback.c,v 1.6 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -30,6 +30,7 @@ static struct __vpirt vpip_callback_rt = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -169,6 +170,12 @@ int vpi_remove_cb(vpiHandle ref)
|
||||
|
||||
/*
|
||||
* $Log: vpi_callback.c,v $
|
||||
* Revision 1.6 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.5 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.4 1999/11/07 20:33:30 steve
|
||||
* Add VCD output and related system tasks.
|
||||
*
|
||||
|
||||
+10
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_const.c,v 1.4 1999/11/06 22:16:50 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_const.c,v 1.6 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -286,6 +286,7 @@ static const struct __vpirt vpip_string_rt = {
|
||||
0,
|
||||
string_value,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -295,6 +296,7 @@ static const struct __vpirt vpip_number_rt = {
|
||||
0,
|
||||
number_value,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -317,6 +319,12 @@ vpiHandle vpip_make_number_const(struct __vpiNumberConst*ref,
|
||||
|
||||
/*
|
||||
* $Log: vpi_const.c,v $
|
||||
* Revision 1.6 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.5 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.4 1999/11/06 22:16:50 steve
|
||||
* Get the $strobe task working.
|
||||
*
|
||||
|
||||
+9
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_iter.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_iter.c,v 1.3 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -34,6 +34,7 @@ static const struct __vpirt vpip_iterator_rt = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -67,6 +68,12 @@ vpiHandle vpi_scan(vpiHandle ref)
|
||||
|
||||
/*
|
||||
* $Log: vpi_iter.c,v $
|
||||
* Revision 1.3 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
|
||||
+131
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Picture Elements, Inc.
|
||||
* Copyright (c) 1999-2000 Picture Elements, Inc.
|
||||
* Stephen Williams (steve@picturel.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -25,8 +25,8 @@
|
||||
* binary (compiled) form. If you have not received it, contact
|
||||
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_memory.c,v 1.1 1999/11/10 02:52:24 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_memory.c,v 1.5 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -51,7 +51,6 @@ static int memory_get(int code, vpiHandle ref)
|
||||
static char* memory_get_str(int code, vpiHandle ref)
|
||||
{
|
||||
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
|
||||
|
||||
assert(ref->vpi_type->type_code==vpiMemory);
|
||||
|
||||
switch (code) {
|
||||
@@ -63,27 +62,155 @@ static char* memory_get_str(int code, vpiHandle ref)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vpiHandle memory_iterate(int code, vpiHandle ref)
|
||||
{
|
||||
unsigned idx;
|
||||
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
|
||||
assert(ref->vpi_type->type_code==vpiMemory);
|
||||
|
||||
switch (code) {
|
||||
case vpiMemoryWord:
|
||||
if (rfp->args == 0) {
|
||||
rfp->args = calloc(rfp->size, sizeof(vpiHandle));
|
||||
for (idx = 0 ; idx < rfp->size ; idx += 1)
|
||||
rfp->args[idx] = &rfp->words[idx].base;
|
||||
}
|
||||
return vpip_make_iterator(rfp->size, rfp->args);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static vpiHandle memory_index(vpiHandle ref, int index)
|
||||
{
|
||||
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
|
||||
assert(ref->vpi_type->type_code==vpiMemory);
|
||||
|
||||
if (rfp->args == 0) {
|
||||
unsigned idx;
|
||||
rfp->args = calloc(rfp->size, sizeof(vpiHandle));
|
||||
for (idx = 0 ; idx < rfp->size ; idx += 1)
|
||||
rfp->args[idx] = &rfp->words[idx].base;
|
||||
}
|
||||
|
||||
if (index > rfp->size) return 0;
|
||||
if (index < 0) return 0;
|
||||
return &(rfp->words[index].base);
|
||||
}
|
||||
|
||||
static int memory_word_get(int code, vpiHandle ref)
|
||||
{
|
||||
struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref;
|
||||
assert(ref->vpi_type->type_code==vpiMemoryWord);
|
||||
|
||||
switch (code) {
|
||||
case vpiSize:
|
||||
return rfp->mem->width;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static vpiHandle memory_word_put(vpiHandle ref, p_vpi_value val,
|
||||
p_vpi_time tim, int flags)
|
||||
{
|
||||
unsigned idx;
|
||||
enum vpip_bit_t*base;
|
||||
struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref;
|
||||
assert(ref->vpi_type->type_code==vpiMemoryWord);
|
||||
|
||||
base = rfp->mem->bits + rfp->index*rfp->mem->width;
|
||||
|
||||
assert(val->format == vpiVectorVal);
|
||||
for (idx = 0 ; idx < rfp->mem->width ; idx += 1) {
|
||||
p_vpi_vecval cur = val->value.vector + (idx/32);
|
||||
int aval = cur->aval >> (idx%32);
|
||||
int bval = cur->bval >> (idx%32);
|
||||
|
||||
if (bval & 1) {
|
||||
if (aval & 1)
|
||||
*base = Vx;
|
||||
else
|
||||
*base = Vz;
|
||||
} else {
|
||||
if (aval & 1)
|
||||
*base = V1;
|
||||
else
|
||||
*base = V0;
|
||||
}
|
||||
base += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void memory_word_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||
{
|
||||
struct __vpiMemoryWord*rfp = (struct __vpiMemorWord*)ref;
|
||||
assert(ref->vpi_type->type_code==vpiMemoryWord);
|
||||
|
||||
vpip_bits_get_value(rfp->mem->bits+rfp->index*rfp->mem->width,
|
||||
rfp->mem->width, vp);
|
||||
}
|
||||
|
||||
static const struct __vpirt vpip_memory_rt = {
|
||||
vpiMemory,
|
||||
memory_get,
|
||||
memory_get_str,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
memory_iterate,
|
||||
memory_index
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_memory_word_rt = {
|
||||
vpiMemoryWord,
|
||||
memory_word_get,
|
||||
0,
|
||||
memory_word_get_value,
|
||||
memory_word_put,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_memory(struct __vpiMemory*ref, const char*name,
|
||||
unsigned wid, unsigned siz)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
ref->base.vpi_type = &vpip_memory_rt;
|
||||
ref->name = name;
|
||||
ref->bits = calloc(wid*siz, sizeof(enum vpip_bit_t));
|
||||
ref->words = calloc(siz, sizeof(struct __vpiMemoryWord));
|
||||
ref->args = 0;
|
||||
ref->width = wid;
|
||||
ref->size = siz;
|
||||
|
||||
for (idx = 0 ; idx < siz ; idx += 1) {
|
||||
ref->words[idx].base.vpi_type = &vpip_memory_word_rt;
|
||||
ref->words[idx].mem = ref;
|
||||
ref->words[idx].index = idx;
|
||||
}
|
||||
|
||||
return &(ref->base);
|
||||
}
|
||||
/*
|
||||
* $Log: vpi_memory.c,v $
|
||||
* Revision 1.5 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 2000/02/13 19:18:28 steve
|
||||
* Accept memory words as parameter to $display.
|
||||
*
|
||||
* Revision 1.3 1999/12/15 04:15:17 steve
|
||||
* Implement vpi_put_value for memory words.
|
||||
*
|
||||
* Revision 1.2 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.1 1999/11/10 02:52:24 steve
|
||||
* Create the vpiMemory handle type.
|
||||
*
|
||||
|
||||
+9
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_null.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_null.c,v 1.3 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -28,6 +28,7 @@ static const struct __vpirt vpip_null_rt = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -37,6 +38,12 @@ struct __vpiNull vpip_null = {
|
||||
|
||||
/*
|
||||
* $Log: vpi_null.c,v $
|
||||
* Revision 1.3 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
|
||||
+39
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_priv.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_priv.c,v 1.5 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -95,6 +95,15 @@ char* vpi_get_str(int property, vpiHandle ref)
|
||||
return (ref->vpi_type->vpi_get_str_)(property, ref);
|
||||
}
|
||||
|
||||
void vpi_get_time(vpiHandle obj, s_vpi_time*t)
|
||||
{
|
||||
s_vpi_value value;
|
||||
vpiHandle tm = vpip_sim_time();
|
||||
value.format = vpiTimeVal;
|
||||
vpi_get_value(tm, &value);
|
||||
memcpy(t, value.value.time, sizeof (*t));
|
||||
}
|
||||
|
||||
void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
|
||||
{
|
||||
if (expr->vpi_type->vpi_get_value_) {
|
||||
@@ -105,6 +114,15 @@ void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
|
||||
vp->format = vpiSuppressVal;
|
||||
}
|
||||
|
||||
vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
||||
s_vpi_time*tp, int flags)
|
||||
{
|
||||
if (obj->vpi_type->vpi_put_value_)
|
||||
return (obj->vpi_type->vpi_put_value_)(obj, vp, tp, flags);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
vpiHandle vpi_handle(int type, vpiHandle ref)
|
||||
{
|
||||
if (type == vpiSysTfCall) {
|
||||
@@ -127,6 +145,12 @@ vpiHandle vpi_iterate(int type, vpiHandle ref)
|
||||
return (ref->vpi_type->iterate_)(type, ref);
|
||||
}
|
||||
|
||||
vpiHandle vpi_handle_by_index(vpiHandle ref, int idx)
|
||||
{
|
||||
assert(ref->vpi_type->index_);
|
||||
return (ref->vpi_type->index_)(ref, idx);
|
||||
}
|
||||
|
||||
void vpi_printf(const char*fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -150,6 +174,18 @@ void vpi_register_systf(const struct t_vpi_systf_data*systf)
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.c,v $
|
||||
* Revision 1.5 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 2000/02/13 19:18:28 steve
|
||||
* Accept memory words as parameter to $display.
|
||||
*
|
||||
* Revision 1.3 2000/01/20 06:04:55 steve
|
||||
* $dumpall checkpointing in VCD dump.
|
||||
*
|
||||
* Revision 1.2 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
|
||||
+25
-5
@@ -1,7 +1,7 @@
|
||||
#ifndef __vpi_priv_H
|
||||
#define __vpi_priv_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-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
|
||||
@@ -18,8 +18,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_priv.h,v 1.8 1999/11/28 00:56:08 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_priv.h,v 1.11 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -61,10 +61,12 @@ struct __vpirt {
|
||||
int (*vpi_get_)(int, vpiHandle);
|
||||
char* (*vpi_get_str_)(int, vpiHandle);
|
||||
void (*vpi_get_value_)(vpiHandle, p_vpi_value);
|
||||
vpiHandle (*vpi_put_value_)(vpiHandle, p_vpi_value, p_vpi_time, int);
|
||||
|
||||
/* These methods follow references. */
|
||||
vpiHandle (*handle_)(int, vpiHandle);
|
||||
vpiHandle (*iterate_)(int, vpiHandle);
|
||||
vpiHandle (*index_)(vpiHandle, int);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -85,7 +87,6 @@ struct __vpiCallback {
|
||||
*/
|
||||
struct __vpiIterator {
|
||||
struct __vpiHandle base;
|
||||
|
||||
vpiHandle *args;
|
||||
unsigned nargs;
|
||||
unsigned next;
|
||||
@@ -93,17 +94,27 @@ struct __vpiIterator {
|
||||
|
||||
/*
|
||||
* Memory is an array of bits that is accessible in N-bit chunks, with
|
||||
* N being the width of a word.
|
||||
* N being the width of a word. The memory word handle just points
|
||||
* back to the memory and uses an index to identify its position in
|
||||
* the memory.
|
||||
*/
|
||||
struct __vpiMemory {
|
||||
struct __vpiHandle base;
|
||||
/* The signal has a name (this points to static memory.) */
|
||||
const char*name;
|
||||
enum vpip_bit_t*bits;
|
||||
struct __vpiMemoryWord*words;
|
||||
vpiHandle*args;
|
||||
unsigned width;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
struct __vpiMemoryWord {
|
||||
struct __vpiHandle base;
|
||||
struct __vpiMemory*mem;
|
||||
int index;
|
||||
};
|
||||
|
||||
/*
|
||||
* This type is occasionally useful. Really! And while we're at it,
|
||||
* create a single instance of the null object. (This is all we need.)
|
||||
@@ -274,6 +285,15 @@ extern int vpip_finished();
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.11 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.10 2000/02/13 19:18:28 steve
|
||||
* Accept memory words as parameter to $display.
|
||||
*
|
||||
* Revision 1.9 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.8 1999/11/28 00:56:08 steve
|
||||
* Build up the lists in the scope of a module,
|
||||
* and get $dumpvars to scan the scope for items.
|
||||
|
||||
+27
-3
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_scope.c,v 1.2 1999/11/28 00:56:08 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_scope.c,v 1.5 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -27,7 +27,8 @@
|
||||
static vpiHandle module_iter(int code, vpiHandle obj)
|
||||
{
|
||||
struct __vpiScope*ref = (struct __vpiScope*)obj;
|
||||
assert(obj->vpi_type->type_code == vpiModule);
|
||||
assert((obj->vpi_type->type_code == vpiModule)
|
||||
|| (obj->vpi_type->type_code == vpiNamedBegin));
|
||||
|
||||
switch (code) {
|
||||
case vpiInternalScope:
|
||||
@@ -42,6 +43,17 @@ static const struct __vpirt vpip_module_rt = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
module_iter
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_named_begin_rt = {
|
||||
vpiNamedBegin,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
module_iter
|
||||
};
|
||||
|
||||
@@ -54,6 +66,9 @@ vpiHandle vpip_make_scope(struct __vpiScope*ref, int type, const char*name)
|
||||
case vpiModule:
|
||||
ref->base.vpi_type = &vpip_module_rt;
|
||||
break;
|
||||
case vpiNamedBegin:
|
||||
ref->base.vpi_type = &vpip_named_begin_rt;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -75,6 +90,15 @@ void vpip_attach_to_scope(struct __vpiScope*ref, vpiHandle obj)
|
||||
|
||||
/*
|
||||
* $Log: vpi_scope.c,v $
|
||||
* Revision 1.5 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 1999/12/15 18:21:20 steve
|
||||
* Support named begin scope at run time.
|
||||
*
|
||||
* Revision 1.3 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.2 1999/11/28 00:56:08 steve
|
||||
* Build up the lists in the scope of a module,
|
||||
* and get $dumpvars to scan the scope for items.
|
||||
|
||||
+10
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_signal.c,v 1.5 1999/11/07 20:33:30 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_signal.c,v 1.7 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -71,6 +71,7 @@ static const struct __vpirt vpip_net_rt = {
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -88,6 +89,7 @@ static const struct __vpirt vpip_reg_rt = {
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -101,6 +103,12 @@ vpiHandle vpip_make_reg(struct __vpiSignal*ref, const char*name)
|
||||
|
||||
/*
|
||||
* $Log: vpi_signal.c,v $
|
||||
* Revision 1.7 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.5 1999/11/07 20:33:30 steve
|
||||
* Add VCD output and related system tasks.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_simulation.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_simulation.c,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -195,6 +195,9 @@ void vpip_simulation_run()
|
||||
|
||||
/*
|
||||
* $Log: vpi_simulation.c,v $
|
||||
* Revision 1.2 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
|
||||
+9
-2
@@ -16,8 +16,8 @@
|
||||
* 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)
|
||||
#ident "$Id: vpi_systask.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_systask.c,v 1.3 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -41,11 +41,18 @@ const struct __vpirt vpip_systask_rt = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
systask_iter
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: vpi_systask.c,v $
|
||||
* Revision 1.3 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user