diff --git a/Makefile.in b/Makefile.in index 179c94265..7753a0aad 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.87 2000/12/06 06:31:09 steve Exp $" +#ident "$Id: Makefile.in,v 1.88 2000/12/09 01:17:38 steve Exp $" # # SHELL = /bin/sh @@ -48,14 +48,23 @@ CPPFLAGS = @CPPFLAGS@ @DEFS@ CXXFLAGS = @CXXFLAGS@ -I$(srcdir) LDFLAGS = @LDFLAGS@ +# The TARGETS variable lists the target modules that can be build and +# installed. Some of them depend on external things, so are only +# compiled if the prerequisites are installed. +TARGETS = tgt-null +ifeq ('@HAVE_IPAL@','yes') +TARGETS += tgt-pal +endif + + all: ivl@EXEEXT@ cd vvm ; $(MAKE) all cd vpi ; $(MAKE) all cd ivlpp ; $(MAKE) all cd driver ; $(MAKE) all - cd tgt-null ; $(MAKE) all cd tgt-verilog ; $(MAKE) all cd tgt-stub ; $(MAKE) all + for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) all); done # This rule rules the compiler in the trivial hello.vl program to make # sure the basics were compiled properly. @@ -70,9 +79,9 @@ clean: cd vpi ; $(MAKE) clean cd driver ; $(MAKE) clean cd ivlpp ; $(MAKE) clean - cd tgt-null ; $(MAKE) clean cd tgt-verilog ; $(MAKE) clean cd tgt-stub ; $(MAKE) clean + for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) clean); done distclean: clean rm -f vvm/Makefile @@ -149,7 +158,7 @@ install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $ cd vpi ; $(MAKE) install cd ivlpp ; $(MAKE) install cd driver ; $(MAKE) install - cd tgt-null ; $(MAKE) install + for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done $(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@ $(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@ @@ -173,7 +182,7 @@ uninstall: cd vpi ; $(MAKE) uninstall cd vvm ; $(MAKE) uninstall cd ivlpp ; $(MAKE) uninstall - cd tgt-null ; $(MAKE) uninstall + for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) uninstall); done -include $(patsubst %.o, dep/%.d, $O) diff --git a/configure.in b/configure.in index 550913207..1c8e4c11a 100644 --- a/configure.in +++ b/configure.in @@ -6,12 +6,15 @@ AC_PROG_CC AC_PROG_CXX AC_CHECK_TOOL(STRIP, strip, true) AC_CHECK_HEADERS(getopt.h) +AC_CHECK_HEADER(ipal.h, HAVE_IPAL=yes, HAVE_IPAL=) AC_PROG_INSTALL AC_CHECK_LIB(dl,main,[DLLIB=-ldl]) AC_SUBST(DLLIB) AC_CANONICAL_HOST # $host +AC_SUBST(HAVE_IPAL) + ####################### ## test for underscores. The vpi module loader in vvm needs to know this ## in order to know the name of the start symbol for the .vpi module. @@ -92,4 +95,4 @@ AC_SUBST(rdynamic) AC_MSG_RESULT($rdynamic) -AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile) +AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile) diff --git a/examples/pal_reg.v b/examples/pal_reg.v new file mode 100644 index 000000000..2948a6904 --- /dev/null +++ b/examples/pal_reg.v @@ -0,0 +1,93 @@ +/* + * 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 + */ + +/* + * This example shows how to use Icarus Verilog to generate PLD output. + * The design is intended to fit into a 22v10 in a PLCC package, with + * pin assignments locked down by design. + */ + +/* + * The register module is an 8 bit register that copies the input to + * the output registers on the rising edge of the clk input. The output + * drivers are controled by a single active low output enable. + * + * This module contains all the logic of the device, but includes nothing + * that has anything to do with the real hardware. + */ +module register (out, val, clk, oe); + + output [7:0] out; + input [7:0] val; + input clk, oe; + + reg [7:0] Q; + + wire [7:0] out; + + bufif0 drv[7:0](out, Q, oe); + + always @(posedge clk) Q = val; + +endmodule + + +/* + * The module pal is used to attach pin information to all the pins of + * the device. We use this to lock down the pin assignments of the + * synthesized result. The pin number assignments are for a 22v10 in + * a PLCC package. + */ +module pal; + + wire out7, out6, out5, out4, out3, out2, out1, out0; + wire inp7, inp6, inp5, inp4, inp3, inp2, inp1, inp0; + wire clk, oe; + + // The PAD attributes attach the wires to pins of the + // device. Output pins are prefixed by a 'o', and input pins by an + // 'i'. If not all the available output pins are used, then the + // remaining are available for the synthesizer to drop internal + // registers or extra logic layers. + $attribute(out7, "PAD", "o27"); + $attribute(out6, "PAD", "o26"); + $attribute(out5, "PAD", "o25"); + $attribute(out4, "PAD", "o24"); + $attribute(out3, "PAD", "o23"); + $attribute(out2, "PAD", "o21"); + $attribute(out1, "PAD", "o20"); + $attribute(out0, "PAD", "o19"); + + $attribute(inp7, "PAD", "i10"); + $attribute(inp6, "PAD", "i9"); + $attribute(inp5, "PAD", "i7"); + $attribute(inp4, "PAD", "i6"); + $attribute(inp3, "PAD", "i5"); + $attribute(inp2, "PAD", "i4"); + $attribute(inp1, "PAD", "i3"); + $attribute(inp0, "PAD", "i2"); + + //$attribute(clk, "PAD", "CLK"); + $attribute(oe, "PAD", "i13"); + + register dev({out7, out6, out5, out4, out3, out2, out1, out0}, + {inp7, inp6, inp5, inp4, inp3, inp2, inp1, inp0}, + clk, oe); + +endmodule // pal diff --git a/tgt-pal/.cvsignore b/tgt-pal/.cvsignore new file mode 100644 index 000000000..1a1fec474 --- /dev/null +++ b/tgt-pal/.cvsignore @@ -0,0 +1,3 @@ +dep +Makefile +pal.tgt diff --git a/tgt-pal/Makefile.in b/tgt-pal/Makefile.in new file mode 100644 index 000000000..e31814a8a --- /dev/null +++ b/tgt-pal/Makefile.in @@ -0,0 +1,83 @@ +# +# This source code is free software; you can redistribute it +# and/or modify it in source code form under the terms of the GNU +# Library 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 Library General Public License for more details. +# +# You should have received a copy of the GNU Library 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 +# +#ident "$Id: Makefile.in,v 1.1 2000/12/09 01:17:38 steve Exp $" +# +# +SHELL = /bin/sh + +VERSION = 0.0 + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +srcdir = @srcdir@ + +VPATH = $(srcdir) + +bindir = @bindir@ +libdir = @libdir@ +includedir = $(prefix)/include + +CC = @CC@ +CXX = @CXX@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +CPPFLAGS = @CPPFLAGS@ @DEFS@ @PICFLAG@ +CXXFLAGS = @CXXFLAGS@ +LDFLAGS = @LDFLAGS@ + +all: pal.tgt + +%.o: %.c + @[ -d dep ] || mkdir dep + $(CC) -Wall $(CPPFLAGS) -I$(srcdir)/.. -MD -c $< -o $*.o + mv $*.d dep + +O = imain.o enables.o pads.o + +ifeq (@CYGWIN@,yes) + TGTLDFLAGS=-Wl,--enable-auto-image-base -L.. -livl + TGTDEPLIBS=../libivl.a +else + TGTLDFLAGS= + TGTDEPLIBS= +endif + + +pal.tgt: $O $(TGTDEPLIBS) + $(CC) -shared -o $@ $O $(TGTLDFLAGS) -lpal + +clean: + rm -f *.o dep/*.d + +install: all installdirs $(libdir)/ivl/pal.tgt + +$(libdir)/ivl/pal.tgt: ./pal.tgt + $(INSTALL_DATA) ./pal.tgt $(libdir)/ivl/pal.tgt + + +installdirs: ../mkinstalldirs + $(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl + +uninstall: + rm -f $(libdir)/ivl/pal.tgt + + +-include $(patsubst %.o, dep/%.d, $O) diff --git a/tgt-pal/enables.c b/tgt-pal/enables.c new file mode 100644 index 000000000..10dd81eba --- /dev/null +++ b/tgt-pal/enables.c @@ -0,0 +1,83 @@ +/* + * 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 + */ +#ident "$Id: enables.c,v 1.1 2000/12/09 01:17:38 steve Exp $" + +# include +# include +# include "priv.h" + + +/* + * Given a pin index, look at the nexus for a bufif device that is + * driving it, if any. + */ +static void absorb_pad_enable(unsigned idx) +{ + unsigned ndx; + ivl_nexus_t nex = bind_pin[idx].nexus; + + for (ndx = 0 ; ndx < ivl_nexus_ptrs(nex) ; ndx += 1) { + + unsigned pin; + ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, ndx); + ivl_net_logic_t log = ivl_nexus_ptr_log(ptr); + + if (log == 0) + continue; + + pin = ivl_nexus_ptr_pin(ptr); + assert(pin == 0); + + switch (ivl_logic_type(log)) { + + case IVL_LO_BUFIF0: + case IVL_LO_BUFIF1: + assert(bind_pin[idx].enable == 0); + bind_pin[idx].enable = log; + break; + + default: + } + } +} + +void absorb_pad_enables(void) +{ + unsigned idx; + + for (idx = 0 ; idx < pins ; idx += 1) { + + if (bind_pin[idx].sop == 0) + continue; + + if (bind_pin[idx].nexus == 0) + continue; + + absorb_pad_enable(idx); + } +} + + +/* + * $Log: enables.c,v $ + * Revision 1.1 2000/12/09 01:17:38 steve + * Add the pal loadable target. + * + */ + diff --git a/tgt-pal/imain.c b/tgt-pal/imain.c new file mode 100644 index 000000000..4eb215ea0 --- /dev/null +++ b/tgt-pal/imain.c @@ -0,0 +1,153 @@ +/* + * 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: imain.c,v 1.1 2000/12/09 01:17:38 steve Exp $" +#endif + +/* + * This module generates a PAL that implements the design. + */ + +# include "priv.h" + +# include +# include +# include +# include + +/* + * As processing proceeds, this variable is incremented as errors are + * encountered. This allows the code generator to give up if it + * detects errors deep within recursive functions. + */ +unsigned pal_errors = 0; + +/* + * This is the pal device that the user asked for. + */ +pal_t pal = 0; + +/* + * These variables are the global pin assignment array. Everything + * operates to build this up. + */ +unsigned pins = 0; +struct pal_bind_s* bind_pin = 0; + +static void dump_final_design(FILE*out) +{ + unsigned idx; + for (idx = 0 ; idx < pins ; idx += 1) { + if (bind_pin[idx].sop) { + fprintf(out, "Output pin %u:\n", idx+1); + fprintf(out, " pin nexus=%s\n", + bind_pin[idx].nexus? + ivl_nexus_name(bind_pin[idx].nexus) : ""); + fprintf(out, " pin enable=%s\n", + bind_pin[idx].enable ? + ivl_logic_name(bind_pin[idx].enable) : "1"); + + } else { + fprintf(out, "Input pin %u:\n", idx+1); + fprintf(out, " pin nexus=%s\n", + bind_pin[idx].nexus? + ivl_nexus_name(bind_pin[idx].nexus) : ""); + } + } +} + + + +/* + * This is the main entry point that Icarus Verilog calls to generate + * code for a pal. + */ +int target_design(ivl_design_t des) +{ + unsigned idx; + const char*part; + ivl_scope_t root; + + /* Get the part type from the design, using the "part" + key. Given the part type, try to open the pal description + so that we can figure out the device. */ + part = ivl_design_flag(des, "part"); + assert(part); + pal = pal_alloc(part); + assert(pal); + + pins = pal_pins(pal); + assert(pins > 0); + + /* Allocate the pin array, ready to start assigning resources. */ + bind_pin = calloc(pins, sizeof (struct pal_bind_s)); + assert(bind_pin); + + /* Connect all the macrocells that drive pins to the pin that + they drive. */ + for (idx = 0 ; idx < pal_sops(pal) ; idx += 1) { + pal_sop_t sop = pal_sop(pal, idx); + int spin = pal_sop_pin(sop); + + if (spin == 0) + continue; + + assert(spin > 0); + bind_pin[spin-1].sop = sop; + } + + + /* Get pin assignments from the user. This is the first and + most constrained step. Everything else must work around the + results of these bindings. */ + root = ivl_design_root(des); + get_pad_bindings(root); + + if (pal_errors) { + fprintf(stderr, "code generator failed.\n"); + pal_free(pal); + return -1; + } + + /* Run through the assigned output pins and absorb the output + enables that are connected to them. */ + absorb_pad_enables(); + + + dump_final_design(stdout); + + pal_free(pal); + return 0; +} + +#ifdef __CYGWIN32__ +#include +DECLARE_CYGWIN_DLL(DllMain); +#endif + +/* + * $Log: imain.c,v $ + * Revision 1.1 2000/12/09 01:17:38 steve + * Add the pal loadable target. + * + * Revision 1.1 2000/12/02 04:50:32 steve + * Make the null target into a loadable target. + * + */ + diff --git a/tgt-pal/pads.c b/tgt-pal/pads.c new file mode 100644 index 000000000..e3733c2db --- /dev/null +++ b/tgt-pal/pads.c @@ -0,0 +1,86 @@ +/* + * 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) +#ident "$Id: pads.c,v 1.1 2000/12/09 01:17:38 steve Exp $" +#endif + +# include "priv.h" +# include +# include +# include + +/* + * This function scans the netlist for all the pin assignments that + * are fixed by a PAD attribute. Search the scopes recursively, + * looking for signals that may have PAD attributes. + */ +int get_pad_bindings(ivl_scope_t net) +{ + unsigned idx; + + int rc = ivl_scope_children(net, get_pad_bindings); + if (rc) + return rc; + + for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1) { + + ivl_signal_t sig; + const char*pad; + int pin; + + sig = ivl_scope_sig(net, idx); + pad = ivl_signal_attr(sig, "PAD"); + if (pad == 0) + continue; + + pin = strtol(pad+1, 0, 10); + if ((pin == 0) || (pin > pins)) { + printf("%s: Invalid PAD assignment: %s\n", + ivl_signal_name(sig), pad); + error_count += 1; + continue; + } + + assert(ivl_signal_pins(sig) == 1); + + if (bind_pin[pin-1].nexus) { + + if (bind_pin[pin-1].nexus != ivl_signal_pin(sig, 0)) { + + printf("%s: Unconnected signals share pin %d\n", + ivl_signal_name(sig), pin); + error_count += 1; + } + + continue; + } + + bind_pin[pin-1].nexus = ivl_signal_pin(sig, 0); + } + + return 0; +} + +/* + * $Log: pads.c,v $ + * Revision 1.1 2000/12/09 01:17:38 steve + * Add the pal loadable target. + * + */ + diff --git a/tgt-pal/priv.h b/tgt-pal/priv.h new file mode 100644 index 000000000..f42150cd1 --- /dev/null +++ b/tgt-pal/priv.h @@ -0,0 +1,59 @@ +#ifndef __priv_H +#define __priv_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) +#ident "$Id: priv.h,v 1.1 2000/12/09 01:17:38 steve Exp $" +#endif + +# include +# include + +extern pal_t pal; + +extern unsigned error_count; + +/* + * A device has an array of pins, that are bound to the netlist either + * by attribute or by random lookup. The bind_pin table keeps track of + * pin allocations. + */ +struct pal_bind_s { + /* This is the netlist connection for the pin. */ + ivl_nexus_t nexus; + /* If the pin is an output, this is is sop that drives it. */ + pal_sop_t sop; + /* If the output has an enable, this is it. */ + ivl_net_logic_t enable; +}; + +extern unsigned pins; +extern struct pal_bind_s* bind_pin; + +extern int get_pad_bindings(ivl_scope_t net); + +extern void absorb_pad_enables(void); + +/* + * $Log: priv.h,v $ + * Revision 1.1 2000/12/09 01:17:38 steve + * Add the pal loadable target. + * + */ +#endif