diff --git a/tgt-edif/.cvsignore b/tgt-edif/.cvsignore new file mode 100644 index 000000000..342bd41b1 --- /dev/null +++ b/tgt-edif/.cvsignore @@ -0,0 +1,6 @@ +configure +Makefile +edif.tgt +dep +config.status +config.log diff --git a/tgt-edif/LICENSE.txt b/tgt-edif/LICENSE.txt new file mode 100644 index 000000000..d908d943f --- /dev/null +++ b/tgt-edif/LICENSE.txt @@ -0,0 +1,46 @@ + +The tgt-edif files are licensed differently from the rest of Icarus +Verilog. These files are: + +-- + +Copyright (c) 2005 Stephen Williams +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-- + +The purpose of the different license here is to allow licensees to use +these files to make EDIF based code generators that use these common +functions without statically linking to GPL files from elsewhere +within Icarus Verilog. + +As a reminder, while this more relaxed license is here to allow +entities to make closed source (binary) code generators, this is not +intended to effect the GPL standing of the rest of Icarus Verilog +source. THIS RELAXED LICENSE APPLIES ONLY TO FILES SPECIFICALLY MARKED +WITH THIS NEW LICENSE. Furthermore, all rights remain reserved. Note +specifically the requirement for you to reproduce notices in your +documentation. + diff --git a/tgt-edif/Makefile.in b/tgt-edif/Makefile.in new file mode 100644 index 000000000..59372c540 --- /dev/null +++ b/tgt-edif/Makefile.in @@ -0,0 +1,139 @@ +# +# Copyright (c) 2005 Stephen Williams +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#ident "$Id: Makefile.in,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $" +# +# +SHELL = /bin/sh + +VERSION = 0.0 + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +srcdir = @srcdir@ +mandir = @mandir@ + +VPATH = $(srcdir) + +bindir = @bindir@ +libdir = @libdir@ +includedir = $(prefix)/include + +CC = @CC@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +RANLIB = @RANLIB@ + +CPPFLAGS = @ident_support@ -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@ +CFLAGS = -Wall @CFLAGS@ +LDFLAGS = @LDFLAGS@ + +all: dep edif.tgt + +dep: + mkdir dep + +%.o: %.c + $(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o + mv $*.d dep + +D = d-lpm.o +O = edif.o device.o target.o gates.o generic.o $D + +ifeq (@WIN32@,yes) + TGTLDFLAGS=-L.. -livl + TGTDEPLIBS=../libivl.a +else + TGTLDFLAGS= + TGTDEPLIBS= +endif + + +edif.tgt: tables.o libedif_tgt.a $(TGTDEPLIBS) + $(CC) @shared@ -o $@ tables.o libedif_tgt.a $(TGTLDFLAGS) + +libedif_tgt.a: $O + rm -f libedif_tgt.a + ar cqv libedif_tgt.a $O + $(RANLIB) libedif_tgt.a + +iverilog-edif.ps: $(srcdir)/iverilog-edif.man + man -t $(srcdir)/iverilog-edif.man > iverilog-edif.ps + +iverilog-edif.pdf: iverilog-edif.ps + ps2pdf iverilog-edif.ps iverilog-edif.pdf + + +Makefile: Makefile.in config.status + ./config.status + +clean: + rm -rf *.o dep edif.tgt + +distclean: clean + rm -f Makefile config.status config.log config.cache + rm -rf autom4te.cache + +check: all + +ifeq (@WIN32@,yes) +#INSTALL_DOC = $(prefix)/iverilog-edif.pdf $(mandir)/man1/iverilog-edif.1 +#INSTALL_DOCDIR = $(mandir)/man1 +all: iverilog-edif.pdf +else +#INSTALL_DOC = $(mandir)/man1/iverilog-edif.1 +#INSTALL_DOCDIR = $(mandir)/man1 +endif + +install: all installdirs $(libdir)/ivl/edif.tgt $(INSTALL_DOC) $(libdir)/ivl/edif.conf $(libdir)/ivl/edif-s.conf + +$(libdir)/ivl/edif.tgt: ./edif.tgt + $(INSTALL_PROGRAM) ./edif.tgt $(libdir)/ivl/edif.tgt + +$(libdir)/ivl/edif.conf: $(srcdir)/edif.conf + $(INSTALL_DATA) $(srcdir)/edif.conf $(libdir)/ivl/edif.conf + +$(libdir)/ivl/edif-s.conf: $(srcdir)/edif-s.conf + $(INSTALL_DATA) $(srcdir)/edif-s.conf $(libdir)/ivl/edif-s.conf + + +$(mandir)/man1/iverilog-edif.1: $(srcdir)/iverilog-edif.man + $(INSTALL_DATA) $(srcdir)/iverilog-edif.man $(mandir)/man1/iverilog-edif.1 + +$(prefix)/iverilog-edif.pdf: iverilog-edif.pdf + $(INSTALL_DATA) iverilog-edif.pdf $(prefix)/iverilog-edif.pdf + +installdirs: ../mkinstalldirs + $(srcdir)/../mkinstalldirs $(libdir)/ivl + +uninstall: + rm -f $(libdir)/ivl/edif.tgt + rm -f $(INSTALL_DOC) + rm -f $(libdir)/ivl/edif-s.conf + rm -f $(libdir)/ivl/edif.conf + +-include $(patsubst %.o, dep/%.d, $O) diff --git a/tgt-edif/configure.in b/tgt-edif/configure.in new file mode 100644 index 000000000..9e047dc3f --- /dev/null +++ b/tgt-edif/configure.in @@ -0,0 +1,28 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(edif.conf) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_RANLIB +AC_PROG_INSTALL + +AC_CANONICAL_HOST +# $host + +# Combined check for Microsoft-related bogosities; sets WIN32 if found +AX_WIN32 + +AC_CHECK_HEADERS(malloc.h) + +# may modify CPPFLAGS and CFLAGS +AX_CPP_PRECOMP + +# Compiler option for position independent code, needed whan making shared objects. +AX_C_PICFLAG + +# linker options when building a shared library +AX_LD_SHAREDLIB_OPTS + +AX_CPP_IDENT + +AC_OUTPUT(Makefile) diff --git a/tgt-edif/d-lpm.c b/tgt-edif/d-lpm.c new file mode 100644 index 000000000..a301fcf41 --- /dev/null +++ b/tgt-edif/d-lpm.c @@ -0,0 +1,904 @@ +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: d-lpm.c,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $" +#endif + +/* + * This is the driver for a purely generic LPM module writer. This + * uses LPM version 2 1 0 devices, without particularly considering + * the target technology. + * + * The LPM standard is EIA-IS/103-A October 1996 + * The output is EDIF 2 0 0 format. + */ + +# include "device.h" +# include "edif_priv.h" +# include "edif.h" +# include "generic.h" +# include +# include + +static edif_cell_t lpm_cell_buf(void) +{ + static edif_cell_t tmp = 0; + + if (tmp != 0) + return tmp; + + tmp = edif_xcell_create(xlib, "BUF", 2); + edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT); + edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT); + + /* A buffer is an inverted inverter. */ + edif_cell_port_pstring(tmp, 0, "LPM_Polarity", "INVERT"); + + edif_cell_pstring(tmp, "LPM_TYPE", "LPM_INV"); + edif_cell_pinteger(tmp, "LPM_Width", 1); + edif_cell_pinteger(tmp, "LPM_Size", 1); + return tmp; +} + +static edif_cell_t lpm_cell_inv(void) +{ + static edif_cell_t tmp = 0; + + if (tmp != 0) + return tmp; + + tmp = edif_xcell_create(xlib, "INV", 2); + edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT); + edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT); + + edif_cell_pstring(tmp, "LPM_TYPE", "LPM_INV"); + edif_cell_pinteger(tmp, "LPM_Width", 1); + edif_cell_pinteger(tmp, "LPM_Size", 1); + return tmp; +} + +static edif_cell_t lpm_cell_bufif0(void) +{ + static edif_cell_t tmp = 0; + + if (tmp != 0) + return tmp; + + tmp = edif_xcell_create(xlib, "BUFIF1", 3); + edif_cell_portconfig(tmp, 0, "TriData", IVL_SIP_OUTPUT); + edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT); + edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT); + + edif_cell_port_pstring(tmp, 2, "LPM_Polarity", "INVERT"); + + edif_cell_pstring(tmp, "LPM_TYPE", "LPM_BUSTRI"); + edif_cell_pinteger(tmp, "LPM_Width", 1); + return tmp; +} + +static edif_cell_t lpm_cell_bufif1(void) +{ + static edif_cell_t tmp = 0; + + if (tmp != 0) + return tmp; + + tmp = edif_xcell_create(xlib, "BUFIF1", 3); + edif_cell_portconfig(tmp, 0, "TriData", IVL_SIP_OUTPUT); + edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT); + edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT); + + edif_cell_pstring(tmp, "LPM_TYPE", "LPM_BUSTRI"); + edif_cell_pinteger(tmp, "LPM_Width", 1); + return tmp; +} + +static edif_cell_t lpm_cell_or(unsigned siz) +{ + unsigned idx; + edif_cell_t cell; + char name[32]; + + sprintf(name, "or%u", siz); + + cell = edif_xlibrary_findcell(xlib, name); + if (cell != 0) + return cell; + + cell = edif_xcell_create(xlib, strdup(name), siz+1); + + edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT); + + for (idx = 0 ; idx < siz ; idx += 1) { + sprintf(name, "Data%ux0", idx); + edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT); + } + + edif_cell_pstring(cell, "LPM_TYPE", "LPM_OR"); + edif_cell_pinteger(cell, "LPM_Width", 1); + edif_cell_pinteger(cell, "LPM_Size", siz); + + return cell; +} + +static edif_cell_t lpm_cell_and(unsigned siz) +{ + unsigned idx; + edif_cell_t cell; + char name[32]; + + sprintf(name, "and%u", siz); + + cell = edif_xlibrary_findcell(xlib, name); + if (cell != 0) + return cell; + + cell = edif_xcell_create(xlib, strdup(name), siz+1); + + edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT); + + for (idx = 0 ; idx < siz ; idx += 1) { + sprintf(name, "Data%ux0", idx); + edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT); + } + + edif_cell_pstring(cell, "LPM_TYPE", "LPM_AND"); + edif_cell_pinteger(cell, "LPM_Width", 1); + edif_cell_pinteger(cell, "LPM_Size", siz); + + return cell; +} + +static edif_cell_t lpm_cell_xor(unsigned siz) +{ + unsigned idx; + edif_cell_t cell; + char name[32]; + + sprintf(name, "xor%u", siz); + + cell = edif_xlibrary_findcell(xlib, name); + if (cell != 0) + return cell; + + cell = edif_xcell_create(xlib, strdup(name), siz+1); + + edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT); + + for (idx = 0 ; idx < siz ; idx += 1) { + sprintf(name, "Data%ux0", idx); + edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT); + } + + edif_cell_pstring(cell, "LPM_TYPE", "LPM_XOR"); + edif_cell_pinteger(cell, "LPM_Width", 1); + edif_cell_pinteger(cell, "LPM_Size", siz); + + return cell; +} + +static edif_cell_t lpm_cell_nor(unsigned siz) +{ + unsigned idx; + edif_cell_t cell; + char name[32]; + + sprintf(name, "nor%u", siz); + + cell = edif_xlibrary_findcell(xlib, name); + if (cell != 0) + return cell; + + cell = edif_xcell_create(xlib, strdup(name), siz+1); + + edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT); + edif_cell_port_pstring(cell, 0, "LPM_Polarity", "INVERT"); + + for (idx = 0 ; idx < siz ; idx += 1) { + sprintf(name, "Data%ux0", idx); + edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT); + } + + edif_cell_pstring(cell, "LPM_TYPE", "LPM_OR"); + edif_cell_pinteger(cell, "LPM_Width", 1); + edif_cell_pinteger(cell, "LPM_Size", siz); + + return cell; +} + +static void lpm_show_header(ivl_design_t des) +{ + unsigned idx; + ivl_scope_t root = ivl_design_root(des); + unsigned sig_cnt = ivl_scope_sigs(root); + unsigned nports = 0, pidx; + + /* Count the ports I'm going to use. */ + for (idx = 0 ; idx < sig_cnt ; idx += 1) { + ivl_signal_t sig = ivl_scope_sig(root, idx); + + if (ivl_signal_port(sig) == IVL_SIP_NONE) + continue; + + if (ivl_signal_attr(sig, "PAD") != 0) + continue; + + nports += ivl_signal_pins(sig); + } + + /* Create the base edf object. */ + edf = edif_create(ivl_scope_basename(root), nports); + + + pidx = 0; + for (idx = 0 ; idx < sig_cnt ; idx += 1) { + edif_joint_t jnt; + ivl_signal_t sig = ivl_scope_sig(root, idx); + + if (ivl_signal_port(sig) == IVL_SIP_NONE) + continue; + + if (ivl_signal_attr(sig, "PAD") != 0) + continue; + + if (ivl_signal_pins(sig) == 1) { + edif_portconfig(edf, pidx, ivl_signal_basename(sig), + ivl_signal_port(sig)); + + assert(ivl_signal_pins(sig) == 1); + jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0)); + edif_port_to_joint(jnt, edf, pidx); + + } else { + const char*name = ivl_signal_basename(sig); + ivl_signal_port_t dir = ivl_signal_port(sig); + char buf[128]; + unsigned bit; + for (bit = 0 ; bit < ivl_signal_pins(sig) ; bit += 1) { + const char*tmp; + sprintf(buf, "%s[%u]", name, bit); + tmp = strdup(buf); + edif_portconfig(edf, pidx+bit, tmp, dir); + + jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit)); + edif_port_to_joint(jnt, edf, pidx+bit); + } + } + + pidx += ivl_signal_pins(sig); + } + + assert(pidx == nports); + + xlib = edif_xlibrary_create(edf, "LPM_LIBRARY"); +} + +static void lpm_show_footer(ivl_design_t des) +{ + edif_print(xnf, edf); +} + +static void hookup_logic_gate(ivl_net_logic_t net, edif_cell_t cell) +{ + unsigned pin, idx; + + edif_joint_t jnt; + edif_cellref_t ref = edif_cellref_create(edf, cell); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); + pin = edif_cell_port_byname(cell, "Result0"); + edif_add_to_joint(jnt, ref, pin); + + for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { + char name[32]; + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx)); + sprintf(name, "Data%ux0", idx-1); + pin = edif_cell_port_byname(cell, name); + edif_add_to_joint(jnt, ref, pin); + } +} + +static void lpm_logic(ivl_net_logic_t net) +{ + edif_cell_t cell; + edif_cellref_t ref; + edif_joint_t jnt; + + switch (ivl_logic_type(net)) { + + case IVL_LO_BUFZ: + case IVL_LO_BUF: + assert(ivl_logic_pins(net) == 2); + cell = lpm_cell_buf(); + ref = edif_cellref_create(edf, cell); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); + edif_add_to_joint(jnt, ref, 0); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1)); + edif_add_to_joint(jnt, ref, 1); + break; + + case IVL_LO_BUFIF0: + assert(ivl_logic_pins(net) == 3); + cell = lpm_cell_bufif0(); + ref = edif_cellref_create(edf, cell); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); + edif_add_to_joint(jnt, ref, 0); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1)); + edif_add_to_joint(jnt, ref, 1); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2)); + edif_add_to_joint(jnt, ref, 2); + break; + + case IVL_LO_BUFIF1: + assert(ivl_logic_pins(net) == 3); + cell = lpm_cell_bufif1(); + ref = edif_cellref_create(edf, cell); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); + edif_add_to_joint(jnt, ref, 0); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1)); + edif_add_to_joint(jnt, ref, 1); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2)); + edif_add_to_joint(jnt, ref, 2); + break; + + case IVL_LO_NOT: + assert(ivl_logic_pins(net) == 2); + cell = lpm_cell_inv(); + ref = edif_cellref_create(edf, cell); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); + edif_add_to_joint(jnt, ref, 0); + + jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1)); + edif_add_to_joint(jnt, ref, 1); + break; + + case IVL_LO_OR: + cell = lpm_cell_or(ivl_logic_pins(net)-1); + hookup_logic_gate(net, cell); + break; + + case IVL_LO_NOR: + cell = lpm_cell_nor(ivl_logic_pins(net)-1); + hookup_logic_gate(net, cell); + break; + + case IVL_LO_AND: + cell = lpm_cell_and(ivl_logic_pins(net)-1); + hookup_logic_gate( net, cell); + break; + + case IVL_LO_XOR: + cell = lpm_cell_xor(ivl_logic_pins(net)-1); + hookup_logic_gate( net, cell); + break; + + default: + fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n", + ivl_logic_type(net)); + break; + } +} + + +static void lpm_show_dff(ivl_lpm_t net) +{ + char name[64]; + edif_cell_t cell; + edif_cellref_t ref; + edif_joint_t jnt; + + unsigned idx; + unsigned pin, wid = ivl_lpm_width(net); + + sprintf(name, "fd%s%s%s%s%s%u", + ivl_lpm_enable(net)? "ce" : "", + ivl_lpm_async_clr(net)? "cl" : "", + ivl_lpm_sync_clr(net)? "sc" : "", + ivl_lpm_async_set(net)? "se" : "", + ivl_lpm_sync_set(net)? "ss" : "", + wid); + + cell = edif_xlibrary_findcell(xlib, name); + + if (cell == 0) { + unsigned nports = 2 * wid + 1; + pin = 0; + if (ivl_lpm_enable(net)) + nports += 1; + if (ivl_lpm_async_clr(net)) + nports += 1; + if (ivl_lpm_sync_clr(net)) + nports += 1; + if (ivl_lpm_async_set(net)) + nports += 1; + if (ivl_lpm_sync_set(net)) + nports += 1; + + cell = edif_xcell_create(xlib, strdup(name), nports); + edif_cell_pstring(cell, "LPM_Type", "LPM_FF"); + edif_cell_pinteger(cell, "LPM_Width", wid); + + for (idx = 0 ; idx < wid ; idx += 1) { + + sprintf(name, "Q%u", idx); + edif_cell_portconfig(cell, idx*2+0, strdup(name), + IVL_SIP_OUTPUT); + + sprintf(name, "Data%u", idx); + edif_cell_portconfig(cell, idx*2+1, strdup(name), + IVL_SIP_INPUT); + } + + pin = wid*2; + + if (ivl_lpm_enable(net)) { + edif_cell_portconfig(cell, pin, "Enable", IVL_SIP_INPUT); + pin += 1; + } + + if (ivl_lpm_async_clr(net)) { + edif_cell_portconfig(cell, pin, "Aclr", IVL_SIP_INPUT); + pin += 1; + } + + if (ivl_lpm_sync_clr(net)) { + edif_cell_portconfig(cell, pin, "Sclr", IVL_SIP_INPUT); + pin += 1; + } + + if (ivl_lpm_async_set(net)) { + edif_cell_portconfig(cell, pin, "Aset", IVL_SIP_INPUT); + pin += 1; + } + + if (ivl_lpm_sync_set(net)) { + edif_cell_portconfig(cell, pin, "Sset", IVL_SIP_INPUT); + pin += 1; + } + + edif_cell_portconfig(cell, pin, "Clock", IVL_SIP_INPUT); + pin += 1; + + assert(pin == nports); + } + + ref = edif_cellref_create(edf, cell); + + pin = edif_cell_port_byname(cell, "Clock"); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net)); + edif_add_to_joint(jnt, ref, pin); + + if (ivl_lpm_enable(net)) { + pin = edif_cell_port_byname(cell, "Enable"); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_enable(net)); + edif_add_to_joint(jnt, ref, pin); + } + + if (ivl_lpm_async_clr(net)) { + pin = edif_cell_port_byname(cell, "Aclr"); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_async_clr(net)); + edif_add_to_joint(jnt, ref, pin); + } + + if (ivl_lpm_sync_clr(net)) { + pin = edif_cell_port_byname(cell, "Sclr"); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_clr(net)); + edif_add_to_joint(jnt, ref, pin); + } + + if (ivl_lpm_async_set(net)) { + pin = edif_cell_port_byname(cell, "Aset"); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_async_set(net)); + edif_add_to_joint(jnt, ref, pin); + } + + if (ivl_lpm_sync_set(net)) { + ivl_expr_t svalue = ivl_lpm_sset_value(net); + + pin = edif_cell_port_byname(cell, "Sset"); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_set(net)); + edif_add_to_joint(jnt, ref, pin); + + edif_cellref_pinteger(ref, "LPM_Svalue", ivl_expr_uvalue(svalue)); + } + + for (idx = 0 ; idx < wid ; idx += 1) { + + sprintf(name, "Q%u", idx); + pin = edif_cell_port_byname(cell, name); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx)); + edif_add_to_joint(jnt, ref, pin); + + sprintf(name, "Data%u", idx); + pin = edif_cell_port_byname(cell, name); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx)); + edif_add_to_joint(jnt, ref, pin); + } +} + +static void lpm_show_mux(ivl_lpm_t net) +{ + edif_cell_t cell; + edif_cellref_t ref; + edif_joint_t jnt; + + unsigned idx, rdx; + + char cellname[32]; + + unsigned wid_r = ivl_lpm_width(net); + unsigned wid_s = ivl_lpm_selects(net); + unsigned wid_z = ivl_lpm_size(net); + + sprintf(cellname, "mux%u_%u_%u", wid_r, wid_s, wid_z); + cell = edif_xlibrary_findcell(xlib, cellname); + + if (cell == 0) { + unsigned pins = wid_r + wid_s + wid_r*wid_z; + + cell = edif_xcell_create(xlib, strdup(cellname), pins); + + /* Make the output ports. */ + for (idx = 0 ; idx < wid_r ; idx += 1) { + sprintf(cellname, "Result%u", idx); + edif_cell_portconfig(cell, idx, strdup(cellname), + IVL_SIP_OUTPUT); + } + + /* Make the select ports. */ + for (idx = 0 ; idx < wid_s ; idx += 1) { + sprintf(cellname, "Sel%u", idx); + edif_cell_portconfig(cell, wid_r+idx, strdup(cellname), + IVL_SIP_INPUT); + } + + for (idx = 0 ; idx < wid_z ; idx += 1) { + unsigned base = wid_r + wid_s + wid_r * idx; + unsigned rdx; + + for (rdx = 0 ; rdx < wid_r ; rdx += 1) { + sprintf(cellname, "Data%ux%u", idx, rdx); + edif_cell_portconfig(cell, base+rdx, strdup(cellname), + IVL_SIP_INPUT); + } + } + + edif_cell_pstring(cell, "LPM_Type", "LPM_MUX"); + edif_cell_pinteger(cell, "LPM_Width", wid_r); + edif_cell_pinteger(cell, "LPM_WidthS", wid_s); + edif_cell_pinteger(cell, "LPM_Size", wid_z); + } + + + ref = edif_cellref_create(edf, cell); + + /* Connect the pins of the instance to the nexa. Access the + cell pins by name. */ + for (idx = 0 ; idx < wid_r ; idx += 1) { + unsigned pin; + + sprintf(cellname, "Result%u", idx); + pin = edif_cell_port_byname(cell, cellname); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx)); + edif_add_to_joint(jnt, ref, pin); + } + + for (idx = 0 ; idx < wid_s ; idx += 1) { + unsigned pin; + + sprintf(cellname, "Sel%u", idx); + pin = edif_cell_port_byname(cell, cellname); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, idx)); + edif_add_to_joint(jnt, ref, pin); + } + + for (idx = 0 ; idx < wid_z ; idx += 1) { + for (rdx = 0 ; rdx < wid_r ; rdx += 1) { + unsigned pin; + + sprintf(cellname, "Data%ux%u", idx, rdx); + pin = edif_cell_port_byname(cell, cellname); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, idx, rdx)); + edif_add_to_joint(jnt, ref, pin); + } + } +} + +static void lpm_show_add(ivl_lpm_t net) +{ + unsigned idx; + unsigned cell_width; + char cellname[32]; + edif_cell_t cell; + edif_cellref_t ref; + edif_joint_t jnt; + + const char*type = "ADD"; + + if (ivl_lpm_type(net) == IVL_LPM_SUB) + type = "SUB"; + + /* Figure out the width of the cell. Normally, it is the LPM + width known by IVL. But if the top data input bits are + unconnected, then we really have a width one less, and we + can use the cout to fill out the output width. */ + cell_width = ivl_lpm_width(net); + if ( (ivl_lpm_data(net,cell_width-1) == 0) + && (ivl_lpm_datab(net,cell_width-1) == 0) ) + cell_width -= 1; + + /* Find the correct ADD/SUB device in the library, search by + name. If the device is not there, then create it and put it + in the library. */ + sprintf(cellname, "%s%u", type, cell_width); + cell = edif_xlibrary_findcell(xlib, cellname); + + if (cell == 0) { + unsigned pins = cell_width * 3 + 1; + + cell = edif_xcell_create(xlib, strdup(cellname), pins); + + for (idx = 0 ; idx < cell_width ; idx += 1) { + + sprintf(cellname, "Result%u", idx); + edif_cell_portconfig(cell, idx*3+0, strdup(cellname), + IVL_SIP_OUTPUT); + + sprintf(cellname, "DataA%u", idx); + edif_cell_portconfig(cell, idx*3+1, strdup(cellname), + IVL_SIP_INPUT); + + sprintf(cellname, "DataB%u", idx); + edif_cell_portconfig(cell, idx*3+2, strdup(cellname), + IVL_SIP_INPUT); + } + + edif_cell_portconfig(cell, pins-1, "Cout", IVL_SIP_OUTPUT); + + edif_cell_pstring(cell, "LPM_Type", "LPM_ADD_SUB"); + edif_cell_pstring(cell, "LPM_Direction", type); + edif_cell_pinteger(cell, "LPM_Width", ivl_lpm_width(net)); + } + + ref = edif_cellref_create(edf, cell); + + /* Connect the pins of the instance to the nexa. Access the + cell pins by name. */ + for (idx = 0 ; idx < cell_width ; idx += 1) { + unsigned pin; + + sprintf(cellname, "Result%u", idx); + pin = edif_cell_port_byname(cell, cellname); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx)); + edif_add_to_joint(jnt, ref, pin); + + sprintf(cellname, "DataA%u", idx); + pin = edif_cell_port_byname(cell, cellname); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx)); + edif_add_to_joint(jnt, ref, pin); + + sprintf(cellname, "DataB%u", idx); + pin = edif_cell_port_byname(cell, cellname); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx)); + edif_add_to_joint(jnt, ref, pin); + } + + if (cell_width < ivl_lpm_width(net)) { + unsigned pin = edif_cell_port_byname(cell, "Cout"); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, cell_width)); + edif_add_to_joint(jnt, ref, pin); + } +} + +static void lpm_show_mult(ivl_lpm_t net) +{ + char name[64]; + unsigned idx; + + edif_cell_t cell; + edif_cellref_t ref; + edif_joint_t jnt; + + sprintf(name, "mult%u", ivl_lpm_width(net)); + cell = edif_xlibrary_findcell(xlib, name); + + if (cell == 0) { + cell = edif_xcell_create(xlib, strdup(name), + 3 * ivl_lpm_width(net)); + + for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) { + + sprintf(name, "Result%u", idx); + edif_cell_portconfig(cell, idx*3+0, + strdup(name), + IVL_SIP_OUTPUT); + + sprintf(name, "DataA%u", idx); + edif_cell_portconfig(cell, idx*3+1, + strdup(name), + IVL_SIP_INPUT); + + sprintf(name, "DataB%u", idx); + edif_cell_portconfig(cell, idx*3+2, + strdup(name), + IVL_SIP_INPUT); + } + + edif_cell_pstring(cell, "LPM_Type", "LPM_MULT"); + edif_cell_pinteger(cell, "LPM_WidthP", ivl_lpm_width(net)); + edif_cell_pinteger(cell, "LPM_WidthA", ivl_lpm_width(net)); + edif_cell_pinteger(cell, "LPM_WidthB", ivl_lpm_width(net)); + } + + ref = edif_cellref_create(edf, cell); + + for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) { + unsigned pin; + ivl_nexus_t nex; + + sprintf(name, "Result%u", idx); + pin = edif_cell_port_byname(cell, name); + + jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx)); + edif_add_to_joint(jnt, ref, pin); + + if ( (nex = ivl_lpm_data(net, idx)) ) { + sprintf(name, "DataA%u", idx); + pin = edif_cell_port_byname(cell, name); + + jnt = edif_joint_of_nexus(edf, nex); + edif_add_to_joint(jnt, ref, pin); + } + + if ( (nex = ivl_lpm_datab(net, idx)) ) { + sprintf(name, "DataB%u", idx); + pin = edif_cell_port_byname(cell, name); + + jnt = edif_joint_of_nexus(edf, nex); + edif_add_to_joint(jnt, ref, pin); + } + } + +} + +static void lpm_show_constant(ivl_net_const_t net) +{ + /* We only need one instance each of constant 0 and 1 bits. If + we need either of them, then create an instance reference and + save that reference here so that later needs for 0 or 1 can + find that the reference already lives and can be added to the + joint. */ + static edif_cellref_t cell0_ref = 0; + static edif_cellref_t cell1_ref = 0; + + static edif_joint_t cell0_jnt = 0; + static edif_joint_t cell1_jnt = 0; + + edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0"); + edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1"); + + const char*bits; + unsigned idx; + + if (cell0 == 0) { + cell0 = edif_xcell_create(xlib, "cell0", 1); + edif_cell_portconfig(cell0, 0, "Result0", IVL_SIP_OUTPUT); + + edif_cell_pstring(cell0, "LPM_Type", "LPM_CONSTANT"); + edif_cell_pinteger(cell0, "LPM_Width", 1); + edif_cell_pinteger(cell0, "LPM_CValue", 0); + } + + if (cell1 == 0) { + cell1 = edif_xcell_create(xlib, "cell1", 1); + edif_cell_portconfig(cell1, 0, "Result0", IVL_SIP_OUTPUT); + + edif_cell_pstring(cell1, "LPM_Type", "LPM_CONSTANT"); + edif_cell_pinteger(cell1, "LPM_Width", 1); + edif_cell_pinteger(cell1, "LPM_CValue", 1); + } + + bits = ivl_const_bits(net); + for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) { + if (bits[idx] == '1') { + if (cell1_ref == 0) { + cell1_ref = edif_cellref_create(edf, cell1); + cell1_jnt = edif_joint_create(edf); + edif_add_to_joint(cell1_jnt, cell1_ref, 0); + } + + } else { + if (cell0_ref == 0) { + cell0_ref = edif_cellref_create(edf, cell0); + cell0_jnt = edif_joint_create(edf); + edif_add_to_joint(cell0_jnt, cell0_ref, 0); + } + } + } + + for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) { + if (bits[idx] == '1') + edif_nexus_to_joint(edf, cell1_jnt, ivl_const_pin(net,idx)); + else + edif_nexus_to_joint(edf, cell0_jnt, ivl_const_pin(net,idx)); + } + +} + + +const struct device_s d_lpm_edif = { + lpm_show_header, + lpm_show_footer, + 0, + 0, + lpm_logic, + lpm_show_dff, /* show_dff */ + 0, + 0, + 0, + 0, /* show_cmp_gt */ + lpm_show_mux, /* show_mux */ + lpm_show_add, /* show_add */ + lpm_show_add, /* show_sub */ + 0, /* show_shiftl */ + 0, /* show_shiftr */ + lpm_show_mult, /* show_mult */ + lpm_show_constant /* show_constant */ +}; + +/* + * $Log: d-lpm.c,v $ + * Revision 1.1.2.1 2005/08/17 01:17:28 steve + * Add the tgt-edif target. + * + */ + diff --git a/tgt-edif/device.c b/tgt-edif/device.c new file mode 100644 index 000000000..85709b8a5 --- /dev/null +++ b/tgt-edif/device.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ident "$Id: device.c,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $" + +# include "device.h" +# include +# include + + +device_t device_from_arch(const char*arch) +{ + unsigned idx; + + assert(arch); + + for (idx = 0 ; edif_device_table[idx].name ; idx += 1) { + if (strcmp(arch, edif_device_table[idx].name) == 0) + return edif_device_table[idx].driver; + + } + + return 0; +} + +/* + * $Log: device.c,v $ + * Revision 1.1.2.1 2005/08/17 01:17:28 steve + * Add the tgt-edif target. + * + */ + diff --git a/tgt-edif/device.h b/tgt-edif/device.h new file mode 100644 index 000000000..3d9045fa4 --- /dev/null +++ b/tgt-edif/device.h @@ -0,0 +1,101 @@ +#ifndef __device_H +#define __device_H +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: device.h,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $" +#endif + +# include + +/* + * This code generator supports a variety of device types. It does + * this by keeping a device "driver" structure for each device + * type. The device structure contains pointers to functions that emit + * the proper XNF for a given type of device. + * + * If a device supports a method, the function pointer is filled in + * with a pointer to the proper function. + * + * If a device does not support the method, then the pointer is null. + */ +typedef const struct device_s* device_t; + +struct device_s { + /* These methods draw leading and trailing format text. */ + void (*show_header)(ivl_design_t des); + void (*show_footer)(ivl_design_t des); + /* Draw scopes marked by ivl_synthesis_cell */ + void (*show_cell_scope)(ivl_scope_t net); + /* Draw pads connected to the specified signal. */ + void (*show_pad)(ivl_signal_t sig, const char*str); + /* Draw basic logic devices. */ + void (*show_logic)(ivl_net_logic_t net); + /* This method emits a D type Flip-Flop */ + void (*show_dff)(ivl_lpm_t net); + /* These methods show various comparators */ + void (*show_cmp_eq)(ivl_lpm_t net); + void (*show_cmp_ne)(ivl_lpm_t net); + void (*show_cmp_ge)(ivl_lpm_t net); + void (*show_cmp_gt)(ivl_lpm_t net); + /* This method draws MUX devices */ + void (*show_mux)(ivl_lpm_t net); + /* This method draws ADD devices */ + void (*show_add)(ivl_lpm_t net); + void (*show_sub)(ivl_lpm_t net); + /* These methods draw SHIFT devices */ + void (*show_shiftl)(ivl_lpm_t net); + void (*show_shiftr)(ivl_lpm_t net); + /* Multipliers */ + void (*show_mult)(ivl_lpm_t net); + /* Constants */ + void (*show_constant)(ivl_net_const_t net); +}; + +/* + * Return the device_t cookie given the name of the architecture. If + * the device is not found, return 0. + * + * This function is used if the user specifies the archetecture + * explicitly, with the -parch=name flag. + */ +extern device_t device_from_arch(const char*arch); + +/* + */ +extern const struct device_table_s { + const char*name; + device_t driver; +} edif_device_table[]; + +/* + * $Log: device.h,v $ + * Revision 1.1.2.1 2005/08/17 01:17:28 steve + * Add the tgt-edif target. + * + */ +#endif diff --git a/tgt-edif/edif-s.conf b/tgt-edif/edif-s.conf new file mode 100644 index 000000000..875c8bc06 --- /dev/null +++ b/tgt-edif/edif-s.conf @@ -0,0 +1,7 @@ +functor:synth2 +functor:synth +functor:syn-rules +#functor:cprop +functor:nodangle +-t:dll +flag:DLL=edif.tgt diff --git a/tgt-edif/edif.c b/tgt-edif/edif.c new file mode 100644 index 000000000..68c8d7152 --- /dev/null +++ b/tgt-edif/edif.c @@ -0,0 +1,678 @@ +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: edif.c,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $" +#endif + +# include "edif.h" +# include +# include +#ifdef HAVE_MALLOC_H +# include +#endif +# include + +typedef enum property_e { + PRP_NONE = 0, + PRP_STRING, + PRP_INTEGER +} property_t; + +struct cellref_property_ { + const char*name; + property_t ptype; + union { + const char*str; + long num; + } value_; + struct cellref_property_*next; +}; + +/* + * This is the root of an EDIF design. From here we can get at the + * root ports of the design (which are typically the pins of a chip or + * FPGA design) a list of external cell libraries, cells properties + * and nexa (joints). + */ +struct edif_s { + const char*name; + /* List the ports of the design. */ + unsigned nports; + struct __cell_port*ports; + /* All the external libraries attached to me. */ + edif_xlibrary_t xlibs; + /* list the cellref instances. */ + edif_cellref_t celref; + /* The root instance has cellref properties as well. */ + struct cellref_property_*property; + /* Keep a list of all the nexa */ + struct edif_joint_s*nexa; +}; + +struct edif_xlibrary_s { + /* Name of this library. */ + const char*name; + /* The cells that are contained in this library. */ + struct edif_cell_s*cells; + /* point to the optional celltable. */ + const struct edif_xlib_celltable*celltable; + /* used to list libraries in an edif_t. */ + struct edif_xlibrary_s*next; +}; + + +struct __cell_port { + const char*name; + const char*ename; + struct cellref_property_*property; + ivl_signal_port_t dir; +}; + +struct edif_cell_s { + const char*name; + edif_xlibrary_t xlib; + + unsigned nports; + struct __cell_port*ports; + + struct cellref_property_*property; + struct edif_cell_s*next; +}; + +struct edif_cellref_s { + struct edif_cell_s* cell; + unsigned u; + struct cellref_property_*property; + struct edif_cellref_s* next; +}; + +struct joint_cell_ { + struct edif_cellref_s*cell; + unsigned port; + struct joint_cell_*next; +}; + +/* + * Joints link cell ports together. The edif_t object contains a list + * of these joints, and each joint lists the ports that are connected + * together. The port is represented by a joint_cell_. + * + * The links list a singly linked list of joint_cell_ objects. To add + * a new link, simply push a new joint_cell_ into the links list. See + * the edif_add_to_joint and edif_port_to_joint functions. + * + * The joints themselves are kept in a singly linked list in the + * edif_t object. To create a new joint, simply push an initialized + * edif_joint_s onto the nexa member of the edif_t object. See the + * edif_joint_create function. + */ +struct edif_joint_s { + const char*name; + struct joint_cell_*links; + struct edif_joint_s*next; +}; + + +static int is_edif_name(const char*text) +{ + static const char*edif_name_chars = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + return (strspn(text, edif_name_chars) == strlen(text)); +} + +edif_t edif_create(const char*design_name, unsigned nports) +{ + edif_t edf = malloc(sizeof(struct edif_s)); + + edf->name = design_name; + edf->nports= nports; + edf->ports = nports? calloc(nports, sizeof(struct __cell_port)) : 0; + edf->celref= 0; + edf->xlibs = 0; + edf->property = 0; + edf->nexa = 0; + + return edf; +} + +void edif_portconfig(edif_t edf, unsigned idx, + const char*name, ivl_signal_port_t dir) +{ + assert(idx < edf->nports); + + edf->ports[idx].name = name; + if (is_edif_name(name)) { + edf->ports[idx].ename = 0; + + } else { + char buf[16]; + sprintf(buf, "PORT%u", idx); + edf->ports[idx].ename = strdup(buf); + } + + edf->ports[idx].dir = dir; +} + +void edif_port_to_joint(edif_joint_t jnt, edif_t edf, unsigned port) +{ + struct joint_cell_* jc = malloc(sizeof(struct joint_cell_)); + + jc->cell = 0; + jc->port = port; + jc->next = jnt->links; + jnt->links = jc; +} + +void edif_pstring(edif_t edf, const char*name, const char*value) +{ + struct cellref_property_*prp = malloc(sizeof(struct cellref_property_)); + prp->name = name; + prp->ptype = PRP_STRING; + prp->value_.str = value; + prp->next = edf->property; + edf->property = prp; +} + +edif_xlibrary_t edif_xlibrary_create(edif_t edf, const char*name) +{ + edif_xlibrary_t xlib = malloc(sizeof(struct edif_xlibrary_s)); + + xlib->name = name; + xlib->cells = 0; + xlib->celltable = 0; + xlib->next = edf->xlibs; + edf->xlibs = xlib; + + return xlib; +} + +void edif_xlibrary_set_celltable(edif_xlibrary_t xlib, + const struct edif_xlib_celltable*tab) +{ + assert(xlib->celltable == 0); + xlib->celltable = tab; +} + +edif_cell_t edif_xlibrary_findcell(edif_xlibrary_t xlib, + const char*cell_name) +{ + const struct edif_xlib_celltable*tcur; + edif_cell_t cur; + + for (cur = xlib->cells ; cur ; cur = cur->next) { + if (strcmp(cell_name, cur->name) == 0) + return cur; + } + + if (xlib->celltable == 0) + return 0; + + for (tcur = xlib->celltable ; tcur->cell_name ; tcur += 1) + if (strcmp(cell_name, tcur->cell_name) == 0) { + return (tcur->cell_func)(xlib); + } + + return 0; +} + +edif_cell_t edif_xlibrary_scope_cell(edif_xlibrary_t xlib, + ivl_scope_t scope) +{ + unsigned port_count, idx; + edif_cell_t cur; + + /* Check to see if the cell is already somehow defined. */ + cur = edif_xlibrary_findcell(xlib, ivl_scope_tname(scope)); + if (cur) return cur; + + /* Count the ports of the scope. */ + port_count = 0; + for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) { + ivl_signal_t sig = ivl_scope_sig(scope, idx); + + if (ivl_signal_port(sig) == IVL_SIP_NONE) + continue; + + port_count += 1; + } + + cur = edif_xcell_create(xlib, ivl_scope_tname(scope), port_count); + + port_count = 0; + for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) { + ivl_signal_t sig = ivl_scope_sig(scope, idx); + + if (ivl_signal_port(sig) == IVL_SIP_NONE) + continue; + + edif_cell_portconfig(cur, port_count, + ivl_signal_basename(sig), + ivl_signal_port(sig)); + port_count += 1; + } + + return cur; +} + +edif_cell_t edif_xcell_create(edif_xlibrary_t xlib, const char*name, + unsigned nports) +{ + unsigned idx; + edif_cell_t cell = malloc(sizeof(struct edif_cell_s)); + + cell->name = name; + cell->xlib = xlib; + cell->nports = nports; + cell->ports = calloc(nports, sizeof(struct __cell_port)); + cell->property = 0; + + for (idx = 0 ; idx < nports ; idx += 1) { + cell->ports[idx].name = "?"; + cell->ports[idx].dir = IVL_SIP_NONE; + cell->ports[idx].property = 0; + } + + cell->next = xlib->cells; + xlib->cells = cell; + + return cell; +} + +void edif_cell_portconfig(edif_cell_t cell, unsigned idx, + const char*name, ivl_signal_port_t dir) +{ + assert(idx < cell->nports); + + cell->ports[idx].name = name; + cell->ports[idx].dir = dir; +} + +void edif_cell_port_pstring(edif_cell_t cell, unsigned idx, + const char*name, const char*value) +{ + struct cellref_property_*prp = malloc(sizeof(struct cellref_property_)); + prp->name = name; + prp->ptype = PRP_STRING; + prp->value_.str = value; + prp->next = cell->ports[idx].property; + cell->ports[idx].property = prp; +} + +unsigned edif_cell_port_byname(edif_cell_t cell, const char*name) +{ + unsigned idx = 0; + for (idx = 0 ; idx < cell->nports ; idx += 1) + if (strcmp(name, cell->ports[idx].name) == 0) + break; + + return idx; +} + +void edif_cell_pstring(edif_cell_t cell, const char*name, + const char*value) +{ + struct cellref_property_*prp = malloc(sizeof(struct cellref_property_)); + prp->name = name; + prp->ptype = PRP_STRING; + prp->value_.str = value; + prp->next = cell->property; + cell->property = prp; +} + +void edif_cell_pinteger(edif_cell_t cell, const char*name, + int value) +{ + struct cellref_property_*prp = malloc(sizeof(struct cellref_property_)); + prp->name = name; + prp->ptype = PRP_INTEGER; + prp->value_.num = value; + prp->next = cell->property; + cell->property = prp; +} + +edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell) +{ + static unsigned u_number = 0; + edif_cellref_t ref = malloc(sizeof(struct edif_cellref_s)); + + u_number += 1; + + assert(cell); + assert(edf); + + ref->u = u_number; + ref->cell = cell; + ref->property = 0; + ref->next = edf->celref; + edf->celref = ref; + + return ref; +} + +void edif_cellref_pstring(edif_cellref_t ref, const char*name, + const char*value) +{ + struct cellref_property_*prp = malloc(sizeof(struct cellref_property_)); + prp->name = name; + prp->ptype = PRP_STRING; + prp->value_.str = value; + prp->next = ref->property; + ref->property = prp; +} + +void edif_cellref_pinteger(edif_cellref_t ref, const char*name, int value) +{ + struct cellref_property_*prp = malloc(sizeof(struct cellref_property_)); + prp->name = name; + prp->ptype = PRP_INTEGER; + prp->value_.num = value; + prp->next = ref->property; + ref->property = prp; +} + +edif_joint_t edif_joint_create(edif_t edf) +{ + edif_joint_t jnt = malloc(sizeof(struct edif_joint_s)); + + jnt->name = 0; + jnt->links = 0; + jnt->next = edf->nexa; + edf->nexa = jnt; + return jnt; +} + +edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex) +{ + void*tmp = ivl_nexus_get_private(nex); + edif_joint_t jnt; + + if (tmp == 0) { + jnt = edif_joint_create(edf); + ivl_nexus_set_private(nex, jnt); + return jnt; + } + + jnt = (edif_joint_t) tmp; + return jnt; +} + +void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex) +{ + void*tmp = ivl_nexus_get_private(nex); + + if (tmp != 0) { + /* There is a joint already on the nexus. Move all the + joint cells to the joint I'm joining to. */ + edif_joint_t njnt = (edif_joint_t)tmp; + while (njnt->links) { + struct joint_cell_*cell = njnt->links; + njnt->links = cell->next; + cell->next = jnt->links; + jnt->links = cell; + } + + /* Now njnt is dead, and should be removed from edif. */ + /* Or we can ignore it as harmless. */ + } + + ivl_nexus_set_private(nex, jnt); +} + +void edif_joint_rename(edif_joint_t jnt, const char*name) +{ + assert(jnt->name == 0); + jnt->name = name; +} + +void edif_add_to_joint(edif_joint_t jnt, edif_cellref_t cell, unsigned port) +{ + struct joint_cell_* jc = malloc(sizeof(struct joint_cell_)); + + jc->cell = cell; + jc->port = port; + jc->next = jnt->links; + jnt->links = jc; +} + +static void fprint_property(FILE*fd, const struct cellref_property_*prp) +{ + fprintf(fd, "(property %s ", prp->name); + switch (prp->ptype) { + case PRP_NONE: + break; + case PRP_STRING: + fprintf(fd, "(string \"%s\")", prp->value_.str); + break; + case PRP_INTEGER: + fprintf(fd, "(integer %ld)", prp->value_.num); + break; + } + fprintf(fd, ")"); +} + +/* + * This function takes all the data structures that have been + * assembled by the code generator, and writes them into an EDIF + * formatted file. + */ +void edif_print(FILE*fd, edif_t edf) +{ + edif_xlibrary_t xlib; + edif_cell_t cell; + edif_cellref_t ref; + edif_joint_t jnt; + struct cellref_property_*prp; + unsigned idx; + + fprintf(fd, "(edif %s\n", edf->name); + fprintf(fd, " (edifVersion 2 0 0)\n"); + fprintf(fd, " (edifLevel 0)\n"); + fprintf(fd, " (keywordMap (keywordLevel 0))\n"); + fprintf(fd, " (status\n"); + fprintf(fd, " (written\n"); + fprintf(fd, " (timeStamp 0 0 0 0 0 0)\n"); + fprintf(fd, " (author \"unknown\")\n"); + fprintf(fd, " (program \"Icarus Verilog/fpga.tgt\")))\n"); + fflush(fd); + + for (xlib = edf->xlibs ; xlib ; xlib = xlib->next) { + + fprintf(fd, " (external %s " + "(edifLevel 0) " + "(technology (numberDefinition))\n", + xlib->name); + + for (cell = xlib->cells ; cell ; cell = cell->next) { + fprintf(fd, " (cell %s (cellType GENERIC)\n", + cell->name); + fprintf(fd, " (view net\n" + " (viewType NETLIST)\n" + " (interface"); + + for (idx = 0 ; idx < cell->nports ; idx += 1) { + struct __cell_port*pp = cell->ports + idx; + fprintf(fd, "\n (port %s", pp->name); + switch (pp->dir) { + case IVL_SIP_INPUT: + fprintf(fd, " (direction INPUT)"); + break; + case IVL_SIP_OUTPUT: + fprintf(fd, " (direction OUTPUT)"); + break; + case IVL_SIP_INOUT: + fprintf(fd, " (direction INOUT)"); + break; + default: + break; + } + + for (prp = pp->property ; prp ; prp=prp->next) { + fprintf(fd, " "); + fprint_property(fd, prp); + } + + fprintf(fd, ")"); + } + + for (prp = cell->property ; prp ; prp = prp->next) { + fprintf(fd, "\n "); + fprint_property(fd, prp); + } + fprintf(fd, ")))\n"); + } + + fprintf(fd, " )\n"); /* terminate (external ...) sexp */ + } + fflush(fd); + + /* Write out the library header */ + fprintf(fd, " (library DESIGN\n"); + fprintf(fd, " (edifLevel 0)\n"); + fprintf(fd, " (technology (numberDefinition))\n"); + + /* The root module is a cell in the library. */ + fprintf(fd, " (cell %s\n", edf->name); + fprintf(fd, " (cellType GENERIC)\n"); + fprintf(fd, " (view net\n"); + fprintf(fd, " (viewType NETLIST)\n"); + fprintf(fd, " (interface\n"); + + for (idx = 0 ; idx < edf->nports ; idx += 1) { + fprintf(fd, " (port "); + if (edf->ports[idx].ename == 0) + fprintf(fd, "%s ", edf->ports[idx].name); + else + fprintf(fd, "(rename %s \"%s\") ", + edf->ports[idx].ename, + edf->ports[idx].name); + + switch (edf->ports[idx].dir) { + case IVL_SIP_INPUT: + fprintf(fd, "(direction INPUT)"); + break; + case IVL_SIP_OUTPUT: + fprintf(fd, "(direction OUTPUT)"); + break; + case IVL_SIP_INOUT: + fprintf(fd, "(direction INOUT)"); + break; + default: + break; + } + fprintf(fd, ")\n"); + } + + fprintf(fd, " )\n"); /* end the (interface ) sexp */ + fflush(fd); + + fprintf(fd, " (contents\n"); + + /* Display all the instances. */ + for (ref = edf->celref ; ref ; ref = ref->next) { + + assert(ref->cell); + + fprintf(fd, "(instance U%u (viewRef net " + "(cellRef %s (libraryRef %s)))", + ref->u, ref->cell->name, ref->cell->xlib->name); + + for (prp = ref->property ; prp ; prp = prp->next) { + fprintf(fd, " "); + fprint_property(fd, prp); + } + + fprintf(fd, ")\n"); + } + + fflush(fd); + + /* Display all the joints. */ + idx = 0; + for (jnt = edf->nexa ; jnt ; jnt = jnt->next, idx += 1) { + struct joint_cell_*jc; + + /* Skip nil joints. */ + if (jnt->links == 0) + continue; + + fprintf(fd, "(net "); + if (jnt->name != 0) + fprintf(fd, "(rename N%u \"%s\")", idx, jnt->name); + else + fprintf(fd, "N%u", idx); + fprintf(fd, " (joined"); + + for (jc = jnt->links ; jc ; jc = jc->next) { + if (jc->cell) { + fprintf(fd, " (portRef %s (instanceRef U%u))", + jc->cell->cell->ports[jc->port].name, + jc->cell->u); + } else { + /* Reference to a port of the main cell. */ + if (edf->ports[jc->port].ename) + fprintf(fd, " (portRef %s)", + edf->ports[jc->port].ename); + else + fprintf(fd, " (portRef %s)", + edf->ports[jc->port].name); + } + } + fprintf(fd, "))\n"); + } + + fprintf(fd, " )\n"); /* end the (contents...) sexp */ + + fprintf(fd, " )\n"); /* end the (view ) sexp */ + fprintf(fd, " )\n"); /* end the (cell ) sexp */ + fprintf(fd, " )\n"); /* end the (library DESIGN) sexp */ + + /* Make an instance of the defined object */ + fprintf(fd, " (design %s\n", edf->name); + fprintf(fd, " (cellRef %s (libraryRef DESIGN))\n", edf->name); + + for (prp = edf->property ; prp ; prp = prp->next) { + fprintf(fd, " "); + fprint_property(fd, prp); + fprintf(fd, "\n"); + } + + fprintf(fd, " )\n"); + + + + fprintf(fd, ")\n"); + fflush(fd); +} + +/* + * $Log: edif.c,v $ + * Revision 1.1.2.1 2005/08/17 01:17:28 steve + * Add the tgt-edif target. + * + */ + diff --git a/tgt-edif/edif.conf b/tgt-edif/edif.conf new file mode 100644 index 000000000..9dd8bab6a --- /dev/null +++ b/tgt-edif/edif.conf @@ -0,0 +1,7 @@ +functor:synth2 +functor:synth +functor:syn-rules +functor:cprop +functor:nodangle +-t:dll +flag:DLL=edif.tgt diff --git a/tgt-edif/edif.h b/tgt-edif/edif.h new file mode 100644 index 000000000..e3de1faa2 --- /dev/null +++ b/tgt-edif/edif.h @@ -0,0 +1,248 @@ +#ifndef __edif_H +#define __edif_H +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: edif.h,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $" +#endif + +# include +# include + +/* + * These types and functions support the task of generating and + * writing out an EDIF 2 0 0 netlist. These functions work by + * supporting the creation of an in-core netlist of the design, then + * writing the netlist out all at once. The library manages cells with + * ports, but does not otherwise interpret cells. They have no + * contents. + * + * The general structure of netlist creation is as follows: + * + * Create a netlist with edif_create(); + * This creates an edif object that represents the design. The + * design is given a name, and that name becomes the name of the + * single cell that this netlist handles. + * + * Add ports to the root with edif_portconfig + * The design may, if it is a macro to be included in a larger + * design, include ports. These are discovered by looking for port + * signals in the root module. + * + * Declare external libraries with edif_xlibrary_create + * Normally, this is the single technology library that contains + * the primitive cells that the code generator intendes to + * use. The library is given a name, such as VIRTEX or whatever + * the implementation tools expect. Cells are attached to the + * library later. An edif netlist may include multiple external + * references. + * + * Declare primitives with edif_xcell_create and edif_cell_portconfig. + * These functions create CELL TYPES that are attached to an + * external library. The libraries are created by + * edif_xlibrary_create. + * + * Cells can be created at any time before their first use. It + * therefore makes the most sense to not create the cell until it + * is certain that they are needed by the design. + * + * Create instances and join them up + * The edif_cellref_t objects represent instances of cells, and + * are the devices of the generated netlist. These cellrefs are + * connected together by the use of edif_joint_t joints. The + * joints can be created from ivl_nexus_t objects, or from their + * own ether. This instantiating of cells and joining them + * together that is the most fun. It is the technology specific + * stuff that the code generator does. + * + * Finally, print the result with edif_print(fd); + * This function writes the netlist in memory to an EDIF file on + * the stdio stream specified. + * + * This library is intended to be used once, to build up a netlist and + * print it. All the names that are taken as const char* should be + * somehow made permanent by the caller. Either they are constant + * strings, or they are strduped as necessary to make them + * permanent. The library will not duplicate them. + */ + +/* TYPE DECLARATIONS */ + +/* This represents the entire EDIF design. You only need one of these + to hold everything. */ +typedef struct edif_s* edif_t; + +/* Each external library of the design gets one of these. */ +typedef struct edif_xlibrary_s* edif_xlibrary_t; + +/* This represents a type of cell. */ +typedef struct edif_cell_s* edif_cell_t; + +/* A cellref is an *instance* of a cell. */ +typedef struct edif_cellref_s* edif_cellref_t; + +/* This represents a generic joint. Cell ports are connected by being + associated with a joint. These can be bound to an ivl_nexus_t + object, of stand along. */ +typedef struct edif_joint_s* edif_joint_t; + +/* This structure defines a table that can be attached to an xlibrary + to incorporate black-box cells to the library. The cell_name is the + name that may be passed to the edif_xlibrary_findcell function, and + the function pointer points to a function that creates the cell and + defines ports for it. A real celltable is terminated by an entry + with a null pointer for the cell_name. */ +struct edif_xlib_celltable { + const char*cell_name; + edif_cell_t (*cell_func)(edif_xlibrary_t xlib); +}; + +/* FUNCTIONS */ + + +/* Start a new EDIF design. The design_name will be used as the name + of the top-mode module of the design. */ +extern edif_t edif_create(const char*design_name, unsigned nports); + +/* macro ports to the design are handled by this library similar to + cells. The user creates ports with this function. This function + configures the sole "port" of the cell with the name and dir passed + in. The direction, in this case, is the *interface* direction. */ +extern void edif_portconfig(edif_t edf, unsigned idx, + const char*name, ivl_signal_port_t dir); + +/* This is like edif_add_to_joint, but works with the edif port. */ +extern void edif_port_to_joint(edif_joint_t jnt, edif_t edf, unsigned port); + +/* The design may have properties attached to it. These properties + will be attached to the instance declared in the footer of the EDIF + file. */ +extern void edif_pstring(edif_t edf, const char*name, const char*value); + +/* Create an external library and attach it to the edif design. This + will lead to a (external ...) declaration of cells that can be used + by the design. */ +extern edif_xlibrary_t edif_xlibrary_create(edif_t edf, const char*name); + +extern void edif_xlibrary_set_celltable(edif_xlibrary_t lib, + const struct edif_xlib_celltable*table); + + +/* External libraries can be searched for existing cells, given a + string name. This function searches for the cell by name, and + returns it. */ +extern edif_cell_t edif_xlibrary_findcell(edif_xlibrary_t lib, + const char*cell_name); + +/* Similar to the above, but it gets the information it needs from the + ivl_scope_t object. */ +extern edif_cell_t edif_xlibrary_scope_cell(edif_xlibrary_t xlib, + ivl_scope_t scope); + +/* Create a new cell, attached to the external library. Specify the + number of ports that the cell has. The edif_cell_portconfig + function is then used to assign name and direction to each of the + ports. + + The cell has a number of pins that are referenced by their number + from 0 to nports-1. You need to remember the pin numbers for the + named ports for use when joining that pin to an edif_joint_t. + + Cellrefs get their port characteristics from the cell that they are + created from. So the pinouts of cellrefs match the pinout of the + associated cell. */ +extern edif_cell_t edif_xcell_create(edif_xlibrary_t, const char*name, + unsigned nports); +extern void edif_cell_portconfig(edif_cell_t cell, unsigned idx, + const char*name, ivl_signal_port_t dir); + +/* Attach a property to a cell port. */ +extern void edif_cell_port_pstring(edif_cell_t cell, unsigned idx, + const char*name, const char*value); + +/* Cells may have properties attached to them. These properties are + included in the library declaration for the cell, instead of the + cell instances. */ +extern void edif_cell_pstring(edif_cell_t cell, const char*name, + const char*value); +extern void edif_cell_pinteger(edif_cell_t cell, const char*name, + int value); + + +/* Ports of cells are normally referenced by their port number. If you + forget what that number is, this function can look it up by name. */ +extern unsigned edif_cell_port_byname(edif_cell_t cell, const char*name); + + +/* Create and instance from a cell. The instance refers to the cell, + which is a type, and contains pips for pins. */ +extern edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell); + +/* Instances can have properties attached to them. The name and value + given here are turned into a (property (string "val")) + sexpression attached to the instance. + + Examples of string properties commonly attached to cellref devices + include such things as the INIT= to initialize LUT cells in + FPGA devices. */ +extern void edif_cellref_pstring(edif_cellref_t ref, const char*name, + const char*value); +extern void edif_cellref_pinteger(edif_cellref_t ref, const char*name, + int value); + +/* This function gets the joint associated with a nexus. This will + create a joint if necessary. */ +extern edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex); + +/* For linking cells outside the ivl netlist, this function creates an + anonymous joint. */ +extern edif_joint_t edif_joint_create(edif_t edf); + +/* Renaming a joint causes it to take on a name when external tools + view the EDIF file. */ +extern void edif_joint_rename(edif_joint_t jnt, const char*name); + +/* Given a joint, this function adds the cell reference. */ +extern void edif_add_to_joint(edif_joint_t jnt, + edif_cellref_t cell, + unsigned port); + +extern void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex); + +/* + * Print the entire design. This should only be done after the design + * is completely assembled. + */ +extern void edif_print(FILE*fd, edif_t design); + +/* + * $Log: edif.h,v $ + * Revision 1.1.2.1 2005/08/17 01:17:29 steve + * Add the tgt-edif target. + * + */ +#endif diff --git a/tgt-edif/edif_priv.h b/tgt-edif/edif_priv.h new file mode 100644 index 000000000..7599705f8 --- /dev/null +++ b/tgt-edif/edif_priv.h @@ -0,0 +1,68 @@ +#ifndef __fpga_priv_H +#define __fpga_priv_H +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: edif_priv.h,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $" +#endif + +# include +# include "device.h" + +/* This is the opened xnf file descriptor. It is the output that this + code generator writes to, whether the format is XNF or EDIF. */ +extern FILE*xnf; + +extern int show_scope_gates(ivl_scope_t net, void*x); + + +extern device_t device; + +extern const char*part; +extern const char*arch; + +/* + * Attribute lookup, should this be provided in ivl_target.h? + */ +int scope_has_attribute(ivl_scope_t s, const char *name); + +/* + * These are mangle functions. + */ +extern void xnf_mangle_logic_name(ivl_net_logic_t net, char*buf, size_t nbuf); +extern void xnf_mangle_lpm_name(ivl_lpm_t net, char*buf, size_t nbuf); + +extern const char*xnf_mangle_nexus_name(ivl_nexus_t net); + + +/* + * $Log: edif_priv.h,v $ + * Revision 1.1.2.1 2005/08/17 01:17:29 steve + * Add the tgt-edif target. + * + */ +#endif diff --git a/tgt-edif/gates.c b/tgt-edif/gates.c new file mode 100644 index 000000000..a0202df91 --- /dev/null +++ b/tgt-edif/gates.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: gates.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $" +#endif + +# include +# include "edif_priv.h" +# include + +static void show_cell_scope(ivl_scope_t scope) +{ + if (device->show_cell_scope == 0) { + fprintf(stderr, "fpga.tgt: ivl_synthesis_cell(scope)" + " not supported by this target.\n"); + return; + } + + device->show_cell_scope(scope); +} + +static void show_gate_logic(ivl_net_logic_t net) +{ + if (device->show_logic == 0) { + fprintf(stderr, "fpga.tgt: IVL LOGIC not supported" + " by this target.\n"); + return; + } + + assert(device->show_logic); + device->show_logic(net); +} + +static void show_gate_lpm(ivl_lpm_t net) +{ + switch (ivl_lpm_type(net)) { + + case IVL_LPM_ADD: + if (device->show_add == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_ADD not supported" + " by this target.\n"); + return; + } + device->show_add(net); + break; + + case IVL_LPM_SUB: + if (device->show_sub == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_SUB not supported" + " by this target.\n"); + return; + } + device->show_sub(net); + break; + + case IVL_LPM_CMP_EQ: + if (device->show_cmp_eq == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_EQ not supported" + " by this target.\n"); + return; + } + device->show_cmp_eq(net); + break; + + case IVL_LPM_CMP_NE: + if (device->show_cmp_ne == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_NE not supported" + " by this target.\n"); + return; + } + device->show_cmp_ne(net); + break; + + case IVL_LPM_CMP_GE: + if (device->show_cmp_ge == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_GE not supported" + " by this target.\n"); + return; + } + device->show_cmp_ge(net); + break; + + case IVL_LPM_CMP_GT: + if (device->show_cmp_gt == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_GT not supported" + " by this target.\n"); + return; + } + device->show_cmp_gt(net); + break; + + case IVL_LPM_FF: + if (device->show_dff == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_FF not supported" + " by this target.\n"); + return; + } + device->show_dff(net); + break; + + case IVL_LPM_MUX: + if (device->show_mux == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_MUX not supported" + " by this target.\n"); + return; + } + device->show_mux(net); + break; + + case IVL_LPM_MULT: + if (device->show_mult == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_MULT not supported" + " by this target.\n"); + return; + } + device->show_mult(net); + break; + + case IVL_LPM_SHIFTL: + if (device->show_shiftl == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTL not supported" + " by this target.\n"); + return; + } + device->show_shiftl(net); + break; + + case IVL_LPM_SHIFTR: + if (device->show_shiftr == 0) { + fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTR not supported" + " by this target.\n"); + return; + } + device->show_shiftr(net); + break; + + default: + fprintf(stderr, "fpga.tgt: unknown LPM type %u\n", + ivl_lpm_type(net)); + break; + } +} + +int show_scope_gates(ivl_scope_t net, void*x) +{ + unsigned idx; + + if (scope_has_attribute(net, "ivl_synthesis_cell")) { + show_cell_scope(net); + return 0; + } + + for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1) + show_gate_logic(ivl_scope_log(net, idx)); + + for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) + show_gate_lpm(ivl_scope_lpm(net, idx)); + + return ivl_scope_children(net, show_scope_gates, 0); +} + +/* + * $Log: gates.c,v $ + * Revision 1.1.2.1 2005/08/17 01:17:29 steve + * Add the tgt-edif target. + * + */ + diff --git a/tgt-edif/generic.c b/tgt-edif/generic.c new file mode 100644 index 000000000..6b0f5eccb --- /dev/null +++ b/tgt-edif/generic.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: generic.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $" +#endif + +# include "generic.h" + +edif_t edf = 0; +edif_xlibrary_t xlib = 0; + +edif_cell_t cell_0 = 0; +edif_cell_t cell_1 = 0; + +edif_cell_t cell_ipad = 0; +edif_cell_t cell_opad = 0; +edif_cell_t cell_iopad = 0; + + + +/* + * $Log: generic.c,v $ + * Revision 1.1.2.1 2005/08/17 01:17:29 steve + * Add the tgt-edif target. + * + */ + diff --git a/tgt-edif/generic.h b/tgt-edif/generic.h new file mode 100644 index 000000000..73ff9f0da --- /dev/null +++ b/tgt-edif/generic.h @@ -0,0 +1,60 @@ +#ifndef __generic_H +#define __generic_H +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: generic.h,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $" +#endif + +# include "edif.h" + +extern edif_t edf; +extern edif_xlibrary_t xlib; + +/* + * The cell_* variables below are the various kinds of devices that + * this family supports as primitives. If the cell type is used at + * least once, then the edif_cell_t is non-zero and will also be + * included in the library declaration. The constants underneath are + * pin assignments for the cell. + */ + +extern edif_cell_t cell_0; +extern edif_cell_t cell_1; + +extern edif_cell_t cell_ipad; +extern edif_cell_t cell_opad; +extern edif_cell_t cell_iopad; + + +/* + * $Log: generic.h,v $ + * Revision 1.1.2.1 2005/08/17 01:17:29 steve + * Add the tgt-edif target. + * + */ +#endif diff --git a/tgt-edif/tables.c b/tgt-edif/tables.c new file mode 100644 index 000000000..8985ac884 --- /dev/null +++ b/tgt-edif/tables.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: tables.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $" +#endif + +# include "device.h" +# include +# include + +/* + * This is where you hook new device types into the module. Simply + * declare your struct device_s objects (as done with d_lpm_edif) and + * add an enty in to the edif_device_table so that the user may invoke + * it via the -parch= command line switch. + */ +extern const struct device_s d_lpm_edif; + +const struct device_table_s edif_device_table[] = { + { "lpm", &d_lpm_edif }, + { 0, 0 } +}; + +/* + * $Log: tables.c,v $ + * Revision 1.1.2.1 2005/08/17 01:17:29 steve + * Add the tgt-edif target. + * + */ + diff --git a/tgt-edif/target.c b/tgt-edif/target.c new file mode 100644 index 000000000..c2fa56c3a --- /dev/null +++ b/tgt-edif/target.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2005 Stephen Williams + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: target.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $" +#endif + + +/* + * This is the EDIF target module. + */ + +# include +# include +# include "edif_priv.h" +# include + +/* This is the opened xnf file descriptor. It is the output that this + code generator writes to. */ +FILE*xnf = 0; + +const char*part = 0; +const char*arch = 0; +device_t device = 0; + +int scope_has_attribute(ivl_scope_t s, const char *name) +{ + int i; + const struct ivl_attribute_s *a; + for (i=0; ikey,name) == 0) + return 1; + } + return 0; +} + +static int show_process(ivl_process_t net, void*x) +{ + ivl_scope_t scope = ivl_process_scope(net); + + /* Ignore processes that are within scopes that are cells. The + cell_scope will generate a cell to represent the entire + scope. */ + if (scope_has_attribute(scope, "ivl_synthesis_cell")) + return 0; + + fprintf(stderr, "fpga target: unsynthesized behavioral code\n"); + return 0; +} + +static void show_pads(ivl_scope_t scope) +{ + unsigned idx; + + if (device->show_pad == 0) + return; + + for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) { + ivl_signal_t sig = ivl_scope_sig(scope, idx); + const char*pad; + + if (ivl_signal_port(sig) == IVL_SIP_NONE) + continue; + + pad = ivl_signal_attr(sig, "PAD"); + if (pad == 0) + continue; + + assert(device->show_pad); + device->show_pad(sig, pad); + } +} + +static void show_constants(ivl_design_t des) +{ + unsigned idx; + + if (device->show_constant == 0) + return; + + for (idx = 0 ; idx < ivl_design_consts(des) ; idx += 1) { + ivl_net_const_t con = ivl_design_const(des, idx); + device->show_constant(con); + } +} + +/* + * This is the main entry point that ivl uses to invoke me, the code + * generator. + */ +int target_design(ivl_design_t des) +{ + ivl_scope_t root = ivl_design_root(des); + const char*path = ivl_design_flag(des, "-o"); + + xnf = fopen(path, "w"); + if (xnf == 0) { + perror(path); + return -1; + } + + part = ivl_design_flag(des, "part"); + if (part && (part[0] == 0)) + part = 0; + + arch = ivl_design_flag(des, "arch"); + if (arch && (arch[0] == 0)) + arch = 0; + + if (arch == 0) + arch = "lpm"; + + device = device_from_arch(arch); + if (device == 0) { + fprintf(stderr, "Unknown architecture arch=%s\n", arch); + return -1; + } + + /* Call the device driver to generate the netlist header. */ + device->show_header(des); + + /* Catch any behavioral code that is left, and write warnings + that it is not supported. */ + ivl_design_process(des, show_process, 0); + + /* Get the pads from the design, and draw them to connect to + the associated signals. */ + show_pads(root); + + /* Scan the scopes, looking for gates to draw into the output + netlist. */ + show_scope_gates(root, 0); + + show_constants(des); + + /* Call the device driver to close out the file. */ + device->show_footer(des); + + fclose(xnf); + xnf = 0; + return 0; +} + +/* + * This function tests whether the nexus has a constant value. It + * returns true if the value is constant, or false if there are + * non-constant or conflicting drivers. + */ +int test_nexus_constant(ivl_nexus_t nex, char*val) +{ + int count_drivers = 0; + unsigned idx; + + for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { + ivl_net_const_t con; + unsigned pin; + const char*cbits; + ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx); + + /* If this nexus link is an input pin to the device (or + otherwise does not drive the nexus) then skip it. */ + if (ivl_nexus_ptr_drive0(ptr) == IVL_DR_HiZ + && ivl_nexus_ptr_drive1(ptr) == IVL_DR_HiZ) + continue; + + count_drivers += 1; + + /* If this driver is not a constant, then the test fails + certainly. */ + con = ivl_nexus_ptr_con(ptr); + if (con == 0) + return 0; + + /* Get the pin number within the constant where this + nexus is connected. */ + pin = ivl_nexus_ptr_pin(ptr); + + /* The pin for the constant that we located is + guaranteed to really point to the nexus that we are + working with. */ + assert(ivl_const_pins(con) > pin); + assert(ivl_const_pin(con,pin) == nex); + + /* Get the bit value from the constant. If there are + multiple constants driving this nexus (an unlikely + situation) then allow for them only if their value + matches. But the more common case is that this is the + only driver for the nexus. Save the constant value in + the *val result that we pass back to the user. */ + cbits = ivl_const_bits(con); + if (count_drivers > 1) { + if (val[0] != cbits[pin]) + return 0; + } else { + val[0] = cbits[pin]; + } + } + + /* If in the end there are no drivers at all for the nexus, + then assume the nexus has a constant HiZ value. */ + if (count_drivers == 0) + *val = 'z'; + + /* Return TRUE */ + return 1; +} + +/* + * $Log: target.c,v $ + * Revision 1.1.2.1 2005/08/17 01:17:29 steve + * Add the tgt-edif target. + * + */ +