Compare commits

...
88 Commits
Author SHA1 Message Date
steve 59c240bc9b I no longer need to declare string and number tables early. 2000-02-24 01:57:10 +00:00
steve d751b05cec change not to v_not. 2000-02-24 01:56:28 +00:00
steve 843af31958 Some compilers do not accept the not symbol. 2000-02-23 04:43:43 +00:00
steve 5aea537ab9 Add Kato to the list. 2000-02-23 04:42:49 +00:00
steve b734ecf02f Macintosh compilers do not support ident. 2000-02-23 02:56:53 +00:00
steve 5b52c384d6 Catch module instantiation arrays. 2000-02-18 05:15:02 +00:00
steve 2cba0a50f3 Fix overlap of identifiers when multiple modules used. 2000-02-17 06:04:30 +00:00
steve b354cf68b8 Fix up width matching in structural bitwise operators. 2000-02-16 03:58:27 +00:00
steve a9264d71c6 Unary reduction operators do not set their operand width 2000-02-14 06:04:52 +00:00
steve e0873f6c14 Support case in functions. 2000-02-14 01:20:50 +00:00
steve b8ddbcf62b support if-else in function definitions. 2000-02-14 00:12:09 +00:00
steve bd09bed662 Mark the line numbers of NetCondit nodes. 2000-02-14 00:11:11 +00:00
steve 1ee4015aa8 Handle selecting memory words at run time. 2000-02-13 19:59:33 +00:00
steve a8d787bd66 Accept memory words as parameter to $display. 2000-02-13 19:18:27 +00:00
steve e77bcf6910 Include some block matching from Larry. 2000-02-13 04:35:43 +00:00
steve 2bc8f79e0f Update xilinx-hints.txt from Larry. 2000-02-13 04:06:49 +00:00
steve e58be1b128 Jason moved. 2000-02-13 04:05:47 +00:00
steve ee180f6cf0 Include the scope in named gates. 2000-02-06 23:13:14 +00:00
steve ce0b97a8f0 Fix up compiling with configured -ldl switch. 2000-02-05 06:40:35 +00:00
steve cf8d17a6ab Handle systems that need underscores in symbols. 2000-01-24 00:18:20 +00:00
steve e6bd088984 Compile time problems with vpi_user.h 2000-01-23 23:54:36 +00:00
steve 9b3c3b6e7a add the -m flag. 2000-01-21 05:41:51 +00:00
steve dc5bd8ea59 $dumpall checkpointing in VCD dump. 2000-01-20 06:04:55 +00:00
steve 121b6c2ecb missing break is switch. 2000-01-18 04:53:57 +00:00
steve 57d28e4f86 Support structural XNOR. 2000-01-18 04:53:40 +00:00
steve d84b72609d Add the XNOR operator. 2000-01-13 06:05:46 +00:00
steve ef98be1192 Support for multiple VPI modules. 2000-01-13 05:11:24 +00:00
steve 3b9dedbc86 Catch some parameter problems. 2000-01-13 04:48:50 +00:00
steve aa8908c52f Multiplication all the way to simulation. 2000-01-13 03:35:35 +00:00
steve 3d1ffced57 Elaborate net widths of constants to as small
as is possible, obeying context constraints.

 Comparison operators can handle operands with
 different widths.
2000-01-11 04:20:57 +00:00
steve f37f69f160 minor type syntax fix for stubborn C++ compilers. 2000-01-10 22:16:24 +00:00
steve fac3bde2c8 Elaborate parameters afer binding of overrides. 2000-01-10 01:35:23 +00:00
steve 9125a4c451 Careful with wires connected to multiple ports. 2000-01-09 20:37:57 +00:00
steve bed47a4ab4 Make the library install directory. 2000-01-09 17:43:28 +00:00
steve 2de887c2ff Support named parameter override lists. 2000-01-09 05:50:48 +00:00
steve fdf2c1b0d0 Non-blocking memory writes. 2000-01-08 03:09:14 +00:00
steve 7f78b9bf56 Handle longer paths and the null target (spe) 2000-01-08 02:28:43 +00:00
steve d6f53b2582 Initial support for signed constants. 2000-01-07 03:45:49 +00:00
steve 848110bc33 Only sign-extend unsized numbers. 2000-01-06 05:57:06 +00:00
steve eb4cdc5026 Cleanup and some asserts. 2000-01-06 05:56:22 +00:00
steve 3d673c1f02 Add memory address range check. 2000-01-06 05:56:02 +00:00
steve a48b4c4f8d Functor support from Stefan 2000-01-04 02:51:54 +00:00
steve ba7fdb580d Add a signal to nexus of padding constant. 2000-01-02 22:07:09 +00:00
steve 9e5ff89ef3 Add structural reduction NAND,
Fix size coercion of structural shifts.
2000-01-02 21:45:31 +00:00
steve 0d5e4b40d0 Structural reduction XNOR. 2000-01-02 19:39:03 +00:00
steve 142b9e667d Do not overrun the pin index when the LSB != 0. 2000-01-02 18:25:37 +00:00
steve f3b76d958d It is possible for node to initialize several pins of a signal. 2000-01-02 17:57:56 +00:00
steve 87d6df5204 Handle nodes running out during node scan. 2000-01-02 17:57:20 +00:00
steve c7193fa6fe Do not delete constants that input to exressions. 2000-01-02 17:56:42 +00:00
steve 645c24289e Handle general constant expressions in delays. 2000-01-02 01:59:52 +00:00
steve e52a5be16e Forgot to handle no overrides at all. 2000-01-02 01:59:28 +00:00
steve 7e37b61a05 Fix module parameter override syntax. 2000-01-01 23:47:58 +00:00
steve cbd353fbb8 Fix forming of ivlpp command line. 2000-01-01 21:33:50 +00:00
steve 4c274223cf Move ivl and ivlpp to the lib directory. 2000-01-01 20:57:50 +00:00
steve 65e4e9f428 Properly expand/shrink constants in expressions. 2000-01-01 19:56:51 +00:00
steve e6820ed169 Handle synthesis of concatenation. 2000-01-01 06:18:00 +00:00
steve c3cb0f2371 Propogate line number information when expanding expressions. 2000-01-01 06:17:25 +00:00
steve 31f1ceea9f delay1 expressions can take parentheses. 1999-12-31 17:39:00 +00:00
steve 94afe54741 Standardize some of the error messages. 1999-12-31 17:38:37 +00:00
steve 080f161c37 Fix output file name calculations. 1999-12-31 05:27:42 +00:00
steve 5ce35e3e60 Fix event trigger and repeat control parse errors. 1999-12-31 03:24:30 +00:00
steve 6d0edcf58a Support reg initial assignment syntax. 1999-12-30 19:06:14 +00:00
steve 7033836e01 Remove the now useless sigfold functor. 1999-12-30 17:37:13 +00:00
steve b7409d98ff Version and ebug options. 1999-12-30 04:59:39 +00:00
steve b6d1bb1fa7 Propogate constant 0 in low bits of adders. 1999-12-30 04:19:12 +00:00
steve 4558a7d8d0 Proper init_ method prototype. 1999-12-19 20:57:07 +00:00
steve 22c2625ace Add the gverilog driver program. 1999-12-18 04:15:01 +00:00
steve 4de8ba489d Rewrite the cprop functor to use the functor_t interface. 1999-12-17 06:18:15 +00:00
steve 65ae92859c NetConst can now hold wide constants. 1999-12-17 03:38:46 +00:00
steve d355270c2d Capture the carry out of carry-chain addition. 1999-12-16 18:54:32 +00:00
steve ced7cc6d60 Structural logical or. 1999-12-16 03:46:39 +00:00
steve d54cc14ca2 Simulate carry output on adders. 1999-12-16 02:42:14 +00:00
steve 98a57f4fac Handle blanks after b is binary numbers 1999-12-16 01:20:17 +00:00
steve 40ca71b10b Support named begin scope at run time. 1999-12-15 18:21:20 +00:00
steve e7e58cdd71 Add readmemb. 1999-12-15 04:35:34 +00:00
steve 1dcf9de34c Implement vpi_put_value for memory words. 1999-12-15 04:15:17 +00:00
steve fcb1d8dc72 Excess warning. 1999-12-15 04:02:38 +00:00
steve 5fa7e1c31b Add the VPI implementation of $readmemh. 1999-12-15 04:01:14 +00:00
steve 6e3c258edb Detect duplicate scopes. 1999-12-14 23:42:16 +00:00
steve 6be5421c8a Remove the useless vvm_simulation class. 1999-12-12 19:47:54 +00:00
steve 76655ce2bb Allow memories without indices in expressions. 1999-12-12 06:03:14 +00:00
steve 3e1738dcec Fix support for attaching attributes to primitive gates. 1999-12-11 05:45:41 +00:00
steve ec8dec74a6 Example how to mke OUTFF devices in IOBs. 1999-12-11 04:10:39 +00:00
steve 838d25890b Various spelling fixes. 1999-12-09 06:00:55 +00:00
steve 4a6d3a5104 Fix const/non-const errors. 1999-12-09 06:00:00 +00:00
steve b688cdbc40 Add some examples as documentation. 1999-12-05 21:08:56 +00:00
steve 09de918198 Generate XNF RAMS from synthesized memories. 1999-12-05 19:30:42 +00:00
steve 3e2bb85f58 Synthesize LPM_RAM_DQ for writes into memories. 1999-12-05 02:24:08 +00:00
118 changed files with 5970 additions and 1841 deletions
+1
View File
@@ -7,6 +7,7 @@ dep
configure
Makefile
verilog
gverilog
config.status
config.log
config.cache
+5 -2
View File
@@ -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
View File
@@ -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
+48 -11
View File
@@ -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.
*
+28 -7
View File
@@ -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
View File
@@ -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.
*
+5 -2
View File
@@ -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.
*
+12 -6
View File
@@ -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
+30 -3
View File
@@ -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
View File
@@ -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.
*
+45 -3
View File
@@ -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.
*
+40 -12
View File
@@ -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.
*
+5 -2
View File
@@ -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.
*
+6 -3
View File
@@ -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.
+6 -3
View File
@@ -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.
*
+5 -2
View File
@@ -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.
*
+6 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+42
View File
@@ -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)
+279 -114
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+14 -3
View File
@@ -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.
+6 -3
View File
@@ -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
View File
@@ -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.
*
+47
View File
@@ -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
+76
View File
@@ -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 */
+114
View File
@@ -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 */
+127
View File
@@ -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 */
+102
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+35 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
+92 -29
View File
@@ -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);
}
+18 -6
View File
@@ -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.
*
+5 -2
View File
@@ -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.
*
+46
View File
@@ -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
View File
@@ -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).
*
+157 -17
View File
@@ -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.
*
+10 -4
View File
@@ -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.
*
+5 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+178 -53
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+142 -168
View File
@@ -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.
*
*/
+25 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
*/
+5 -2
View File
@@ -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
*
+5 -2
View File
@@ -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.
*
+98 -7
View File
@@ -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.
*
+10 -3
View File
@@ -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
View File
@@ -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.
*
+368 -162
View File
@@ -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.
*/
+130 -57
View File
@@ -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
+15 -3
View File
@@ -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.
+9 -2
View File
@@ -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
View File
@@ -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.
*
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+17 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,3 +1,4 @@
Makefile
sys_readmem_lex.c
system.vpi
dep
+7 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+162
View File
@@ -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.
*
*/
+44
View File
@@ -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
+177
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+6 -3
View File
@@ -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
View File
@@ -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)
+46
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+5 -2
View File
@@ -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
View File
@@ -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