Initial BLIF code generator.

Add the -tblif code generator target, and include some basic
useful behavior.
This commit is contained in:
Stephen Williams 2013-07-13 19:06:18 -07:00
parent c4edbda969
commit d2034a6458
9 changed files with 479 additions and 2 deletions

2
.gitignore vendored
View File

@ -51,6 +51,8 @@ dep
*.vpi
/cadpli/cadpli.vpl
/tgt-blif/Makefile
# lex, yacc and gperf output
/driver/cflexor.c
/driver/cfparse.c

View File

@ -38,7 +38,7 @@ srcdir = @srcdir@
datarootdir = @datarootdir@
SUBDIRS = ivlpp vhdlpp vvp vpi libveriuser cadpli tgt-null tgt-stub tgt-vvp \
tgt-vhdl tgt-vlog95 tgt-pcb driver
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif driver
# Only run distclean for these directories.
NOTUSED = tgt-fpga tgt-pal tgt-verilog

View File

@ -325,4 +325,4 @@ AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
fi
AC_MSG_RESULT(ok)
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile)
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile)

104
tgt-blif/Makefile.in Normal file
View File

@ -0,0 +1,104 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
CC = @CC@
CC = @CXX@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I. -I..
else
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CXXFLAGS = @WARNING_FLAGS@ @CXXFLAGS@
LDFLAGS = @LDFLAGS@
O = blif.o nex_data.o
all: dep blif.tgt
check: all
clean:
rm -rf *.o dep blif.tgt
distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=tgt-blif/$@
dep:
mkdir dep
%.o: %.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
TGTDEPLIBS=../libivl.a
else
TGTLDFLAGS=
TGTDEPLIBS=
endif
blif.tgt: $O $(TGTDEPLIBS)
$(CC) @shared@ $(LDFLAGS) -o $@ $O $(TGTLDFLAGS)
install: all installdirs $(libdir)/ivl$(suffix)/blif.tgt $(INSTALL_DOC) $(libdir)/ivl$(suffix)/blif.conf $(libdir)/ivl$(suffix)/blif-s.conf
$(libdir)/ivl$(suffix)/blif.tgt: ./blif.tgt
$(INSTALL_PROGRAM) ./blif.tgt "$(DESTDIR)$(libdir)/ivl$(suffix)/blif.tgt"
$(libdir)/ivl$(suffix)/blif.conf: $(srcdir)/blif.conf
$(INSTALL_DATA) $(srcdir)/blif.conf "$(DESTDIR)$(libdir)/ivl$(suffix)/blif.conf"
$(libdir)/ivl$(suffix)/blif-s.conf: $(srcdir)/blif-s.conf
$(INSTALL_DATA) $(srcdir)/blif-s.conf "$(DESTDIR)$(libdir)/ivl$(suffix)/blif-s.conf"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)/ivl$(suffix)"
uninstall:
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/blif.tgt"
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/blif.conf"
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/blif-s.conf"
-include $(patsubst %.o, dep/%.d, $O)

6
tgt-blif/blif-s.conf Normal file
View File

@ -0,0 +1,6 @@
functor:synth2
functor:synth
functor:syn-rules
functor:cprop
functor:nodangle
flag:DLL=blif.tgt

234
tgt-blif/blif.cc Normal file
View File

@ -0,0 +1,234 @@
/*
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "version_base.h"
# include "version_tag.h"
# include "config.h"
# include "ivl_target.h"
# include "nex_data.h"
# include <vector>
# include <cstdio>
# include <cstring>
# include <cassert>
using namespace std;
/*
* This is a BLIF target module.
*/
static const char*version_string =
"Icarus Verilog BLIF Code Generator " VERSION " (" VERSION_TAG ")\n\n"
"Copyright (c) 2013 Stephen Williams (steve@icarus.com)\n\n"
" This program is free software; you can redistribute it and/or modify\n"
" it under the terms of the GNU General Public License as published by\n"
" the Free Software Foundation; either version 2 of the License, or\n"
" (at your option) any later version.\n"
"\n"
" This program is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License along\n"
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
;
static int emit_blif(const char*blif_path, ivl_scope_t model);
int target_design(ivl_design_t des)
{
int rc = 0;
const char*blif_path = ivl_design_flag(des, "-o");
// Locate the root scope for the design. Note that the BLIF
// format implies that there is a single root of the model.
ivl_scope_t*roots;
unsigned nroots;
ivl_design_roots(des, &roots, &nroots);
if (nroots != 1) {
fprintf(stderr, "BLIF: The BLIF code generator requires that there be only one root scope.\n");
return 1;
}
assert(roots[0]);
if (ivl_scope_type(roots[0]) != IVL_SCT_MODULE) {
fprintf(stderr, "BLIF: The root scope %s must be a module.\n", ivl_scope_basename(roots[0]));
return 1;
}
// Emit to the destination file.
assert(blif_path);
rc += emit_blif(blif_path, roots[0]);
return rc;
}
const char* target_query(const char*key)
{
if (strcmp(key,"version") == 0)
return version_string;
return 0;
}
/*
* Print all the bits of a signal. This is for the .input or .output
* lines of a .model. All the bits need to be exploded, so print each
* bit of a vector as its own name.
*/
static void print_signal_bits(FILE*fd, ivl_signal_t sig)
{
ivl_nexus_t nex = ivl_signal_nex(sig, 0);
blif_nex_data_t* ned = blif_nex_data_t::get_nex_data(nex);
ned->set_name(ivl_signal_basename(sig));
if (ivl_signal_packed_dimensions(sig) == 0) {
fprintf(fd, " %s", ivl_signal_basename(sig));
return;
}
assert(ivl_signal_packed_dimensions(sig) == 1);
int msb = ivl_signal_packed_msb(sig,0);
int lsb = ivl_signal_packed_lsb(sig,0);
if (msb < lsb) {
int tmp = msb;
msb = lsb;
lsb = tmp;
}
for (int idx = msb ; idx >= lsb ; idx -= 1) {
fprintf(fd, " %s[%d]", ivl_signal_basename(sig), idx);
}
}
static void print_logic_gate(FILE*fd, ivl_net_logic_t net)
{
#if 0
fprintf(fd, "# LOGIC: name=%s, type=%d, pins=%u, width=%u\n",
ivl_logic_basename(net), ivl_logic_type(net),
ivl_logic_pins(net), ivl_logic_width(net));
#endif
fprintf(fd, ".names");
ivl_nexus_t nex;
blif_nex_data_t*ned;
for (unsigned idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) {
nex = ivl_logic_pin(net,idx);
ned = blif_nex_data_t::get_nex_data(nex);
fprintf(fd, " %s", ned->get_name());
}
nex = ivl_logic_pin(net,0);
ned = blif_nex_data_t::get_nex_data(nex);
fprintf(fd, " %s", ned->get_name());
fprintf(fd, "\n");
switch (ivl_logic_type(net)) {
case IVL_LO_AND:
for (unsigned idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1)
fprintf(fd, "1");
fprintf(fd, " 1\n");
break;
case IVL_LO_OR:
assert(ivl_logic_pins(net)==3);
fprintf(fd, "1- 1\n");
fprintf(fd, "-1 1\n");
break;
case IVL_LO_XOR:
assert(ivl_logic_pins(net)==3);
fprintf(fd, "10 1\n");
fprintf(fd, "01 1\n");
break;
default:
fprintf(fd, "# ERROR: Logic type not handled\n");
break;
}
}
static int emit_blif(const char*blif_path, ivl_scope_t model)
{
int rc = 0;
FILE*fd = fopen(blif_path, "wt");
if (fd == 0) {
perror(blif_path);
return 1;
}
fprintf(fd, ".model %s\n", ivl_scope_basename(model));
// The root scope
vector<ivl_signal_t> ports_in;
vector<ivl_signal_t> ports_out;
for (unsigned idx = 0 ; idx < ivl_scope_sigs(model) ; idx += 1) {
ivl_signal_t prt = ivl_scope_sig(model, idx);
ivl_signal_port_t dir = ivl_signal_port(prt);
switch (dir) {
case IVL_SIP_NONE:
break;
case IVL_SIP_INPUT:
ports_in.push_back(prt);
break;
case IVL_SIP_OUTPUT:
ports_out.push_back(prt);
break;
case IVL_SIP_INOUT:
fprintf(stderr, "BLIF: error: "
"Model port %s is bi-directional.\n",
ivl_signal_basename(prt));
rc += 1;
ports_in.push_back(prt);
ports_out.push_back(prt);
break;
}
}
if (ports_in.size() > 0) {
fprintf(fd, ".inputs");
for (size_t idx = 0 ; idx < ports_in.size() ; idx += 1) {
ivl_signal_t prt = ports_in[idx];
print_signal_bits(fd, prt);
}
fprintf(fd, "\n");
}
if (ports_out.size() > 0) {
fprintf(fd, ".outputs");
for (size_t idx = 0 ; idx < ports_out.size() ; idx += 1) {
ivl_signal_t prt = ports_out[idx];
print_signal_bits(fd, prt);
}
fprintf(fd, "\n");
}
for (unsigned idx = 0 ; idx < ivl_scope_logs(model) ; idx += 1) {
ivl_net_logic_t net = ivl_scope_log(model, idx);
assert(net);
print_logic_gate(fd, net);
}
fprintf(fd, ".end\n");
fclose(fd);
return rc;
}

3
tgt-blif/blif.conf Normal file
View File

@ -0,0 +1,3 @@
functor:cprop
functor:nodangle
flag:DLL=blif.tgt

74
tgt-blif/nex_data.cc Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "nex_data.h"
# include <cstdlib>
# include <cstdio>
# include <cstring>
# include <cassert>
inline blif_nex_data_t::blif_nex_data_t(ivl_nexus_t nex)
: nex_(nex), name_(0)
{
}
blif_nex_data_t::~blif_nex_data_t()
{
if (name_) free(name_);
}
blif_nex_data_t* blif_nex_data_t::get_nex_data(ivl_nexus_t nex)
{
void*tmp = ivl_nexus_get_private(nex);
if (tmp != 0) return reinterpret_cast<blif_nex_data_t*> (tmp);
blif_nex_data_t*data = new blif_nex_data_t(nex);
ivl_nexus_set_private(nex, data);
return data;
}
void blif_nex_data_t::set_name(const char*txt)
{
assert(name_ == 0);
name_ = strdup(txt);
}
const char* blif_nex_data_t::get_name(void)
{
if (name_) return name_;
for (unsigned idx = 0 ; idx < ivl_nexus_ptrs(nex_) ; idx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex_, idx);
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
if (sig == 0)
continue;
name_ = strdup(ivl_signal_basename(sig));
break;
}
if (name_ == 0) {
char buf[64];
snprintf(buf, sizeof buf, "@%p", nex_);
name_ = strdup(buf);
}
assert(name_);
return name_;
}

54
tgt-blif/nex_data.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef __nex_data_H
#define __nex_data_H
/*
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "ivl_target.h"
/*
* The ivl_target.h API allows for binding data to a nexus. This class
* represents the data that we want to attach to a nexus.
*/
class blif_nex_data_t {
private:
// The constructors are private. Only the get_nex_data()
// function can create these objects.
blif_nex_data_t(ivl_nexus_t nex);
~blif_nex_data_t();
public:
// Return the blif_nex_data_t object that is associated with
// the given nexus. If the nexus does not have a nex_data_t
// object, then create it and bind it to the nexus. Thus, this
// function will always return the same nex_data instance for
// the same nexus.
static blif_nex_data_t* get_nex_data(ivl_nexus_t nex);
void set_name(const char*);
// Get the symbolic name chosen for this nexus.
const char*get_name(void);
public:
ivl_nexus_t nex_;
char*name_;
};
#endif