2013-07-14 04:06:18 +02:00
|
|
|
/*
|
|
|
|
|
* 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"
|
2013-07-19 04:39:49 +02:00
|
|
|
# include "priv.h"
|
2013-07-14 04:06:18 +02:00
|
|
|
# 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"
|
|
|
|
|
;
|
|
|
|
|
|
2013-07-19 04:39:49 +02:00
|
|
|
int blif_errors = 0;
|
|
|
|
|
|
|
|
|
|
static void emit_blif(const char*blif_path, ivl_design_t des, ivl_scope_t model);
|
|
|
|
|
|
|
|
|
|
static int process_scan_fun(ivl_process_t net, void*raw)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "%s:%u: sorry: BLIF: Processes not supported yet.\n",
|
|
|
|
|
ivl_process_file(net), ivl_process_lineno(net));
|
|
|
|
|
blif_errors += 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2013-07-14 04:06:18 +02:00
|
|
|
|
|
|
|
|
int target_design(ivl_design_t des)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-19 04:39:49 +02:00
|
|
|
// Detect processes and dispatch them.
|
|
|
|
|
ivl_design_process(des, &process_scan_fun, 0);
|
|
|
|
|
|
2013-07-14 04:06:18 +02:00
|
|
|
// Emit to the destination file.
|
|
|
|
|
assert(blif_path);
|
2013-07-19 04:39:49 +02:00
|
|
|
emit_blif(blif_path, des, roots[0]);
|
2013-07-14 04:06:18 +02:00
|
|
|
|
2013-07-19 04:39:49 +02:00
|
|
|
return blif_errors;
|
2013-07-14 04:06:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
2013-07-20 05:02:14 +02:00
|
|
|
ned->set_name(sig);
|
2013-07-14 04:06:18 +02:00
|
|
|
|
2013-07-20 05:02:14 +02:00
|
|
|
for (unsigned idx = 0 ; idx < ned->get_width() ; idx += 1) {
|
|
|
|
|
fprintf(fd, " %s%s", ned->get_name(), ned->get_name_index(idx));
|
2013-07-14 04:06:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-19 04:39:49 +02:00
|
|
|
|
|
|
|
|
static void emit_scope(FILE*fd, ivl_scope_t scope)
|
2013-07-14 04:06:18 +02:00
|
|
|
{
|
2013-07-19 04:39:49 +02:00
|
|
|
for (unsigned idx = 0 ; idx < ivl_scope_logs(scope) ; idx += 1) {
|
|
|
|
|
ivl_net_logic_t net = ivl_scope_log(scope, idx);
|
|
|
|
|
assert(net);
|
|
|
|
|
blif_errors += print_logic_gate(fd, net);
|
2013-07-14 04:06:18 +02:00
|
|
|
}
|
2013-07-19 04:39:49 +02:00
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < ivl_scope_lpms(scope) ; idx += 1) {
|
|
|
|
|
ivl_lpm_t net = ivl_scope_lpm(scope, idx);
|
|
|
|
|
blif_errors += print_lpm(fd, net);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t idx = 0 ; idx < ivl_scope_childs(scope) ; idx += 1) {
|
|
|
|
|
ivl_scope_t child = ivl_scope_child(scope, idx);
|
|
|
|
|
emit_scope(fd, child);
|
2013-07-14 04:06:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-19 04:39:49 +02:00
|
|
|
static void emit_blif(const char*blif_path, ivl_design_t des, ivl_scope_t model)
|
2013-07-14 04:06:18 +02:00
|
|
|
{
|
|
|
|
|
FILE*fd = fopen(blif_path, "wt");
|
|
|
|
|
if (fd == 0) {
|
|
|
|
|
perror(blif_path);
|
2013-07-19 04:39:49 +02:00
|
|
|
blif_errors += 1;
|
|
|
|
|
return;
|
2013-07-14 04:06:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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));
|
2013-07-19 04:39:49 +02:00
|
|
|
blif_errors += 1;
|
2013-07-14 04:06:18 +02:00
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-19 04:39:49 +02:00
|
|
|
emit_scope(fd, model);
|
|
|
|
|
|
|
|
|
|
emit_constants(fd, des, model);
|
2013-07-14 04:06:18 +02:00
|
|
|
|
|
|
|
|
fprintf(fd, ".end\n");
|
|
|
|
|
fclose(fd);
|
2013-07-19 04:39:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool scope_is_in_model(ivl_scope_t model, ivl_scope_t scope)
|
|
|
|
|
{
|
|
|
|
|
while (scope) {
|
|
|
|
|
if (scope==model)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
scope = ivl_scope_parent(scope);
|
|
|
|
|
}
|
2013-07-14 04:06:18 +02:00
|
|
|
|
2013-07-19 04:39:49 +02:00
|
|
|
return false;
|
2013-07-14 04:06:18 +02:00
|
|
|
}
|