Add the tgt-edif target.

This commit is contained in:
steve 2005-08-17 01:17:28 +00:00
parent 8c73fa7840
commit 3b753fe52b
17 changed files with 2882 additions and 0 deletions

6
tgt-edif/.cvsignore Normal file
View File

@ -0,0 +1,6 @@
configure
Makefile
edif.tgt
dep
config.status
config.log

46
tgt-edif/LICENSE.txt Normal file
View File

@ -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.

139
tgt-edif/Makefile.in Normal file
View File

@ -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)

28
tgt-edif/configure.in Normal file
View File

@ -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)

904
tgt-edif/d-lpm.c Normal file
View File

@ -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 <string.h>
# include <assert.h>
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.
*
*/

55
tgt-edif/device.c Normal file
View File

@ -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 <string.h>
# include <assert.h>
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.
*
*/

101
tgt-edif/device.h Normal file
View File

@ -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 <ivl_target.h>
/*
* 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

7
tgt-edif/edif-s.conf Normal file
View File

@ -0,0 +1,7 @@
functor:synth2
functor:synth
functor:syn-rules
#functor:cprop
functor:nodangle
-t:dll
flag:DLL=edif.tgt

678
tgt-edif/edif.c Normal file
View File

@ -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 <stdlib.h>
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <assert.h>
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.
*
*/

7
tgt-edif/edif.conf Normal file
View File

@ -0,0 +1,7 @@
functor:synth2
functor:synth
functor:syn-rules
functor:cprop
functor:nodangle
-t:dll
flag:DLL=edif.tgt

248
tgt-edif/edif.h Normal file
View File

@ -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 <stdio.h>
# include <ivl_target.h>
/*
* 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(<name>);
* 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 <name> (string "val"))
sexpression attached to the instance.
Examples of string properties commonly attached to cellref devices
include such things as the INIT=<value> 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

68
tgt-edif/edif_priv.h Normal file
View File

@ -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 <stdio.h>
# 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

192
tgt-edif/gates.c Normal file
View File

@ -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 <ivl_target.h>
# include "edif_priv.h"
# include <assert.h>
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.
*
*/

51
tgt-edif/generic.c Normal file
View File

@ -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.
*
*/

60
tgt-edif/generic.h Normal file
View File

@ -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

54
tgt-edif/tables.c Normal file
View File

@ -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 <string.h>
# include <assert.h>
/*
* 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=<foo> 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.
*
*/

238
tgt-edif/target.c Normal file
View File

@ -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 <ivl_target.h>
# include <string.h>
# include "edif_priv.h"
# include <assert.h>
/* 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; i<ivl_scope_attr_cnt(s); i++) {
a = ivl_scope_attr_val(s, i);
if (strcmp(a->key,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.
*
*/