Add the tgt-edif target.
This commit is contained in:
parent
8c73fa7840
commit
3b753fe52b
|
|
@ -0,0 +1,6 @@
|
|||
configure
|
||||
Makefile
|
||||
edif.tgt
|
||||
dep
|
||||
config.status
|
||||
config.log
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
#functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=edif.tgt
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=edif.tgt
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue