mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-22 00:26:40 +00:00
Merge branch 'YosysHQ:main' into main
This commit is contained in:
commit
fdc4c54c66
2
.github/workflows/prepare-docs.yml
vendored
2
.github/workflows/prepare-docs.yml
vendored
|
@ -32,7 +32,7 @@ jobs:
|
|||
- name: Prepare docs
|
||||
shell: bash
|
||||
run:
|
||||
make docs/prep TARGETS= EXTRA_TARGETS=
|
||||
make docs/prep -j${{ env.procs }} TARGETS= EXTRA_TARGETS=
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
11
Makefile
11
Makefile
|
@ -155,7 +155,7 @@ ifeq ($(OS), Haiku)
|
|||
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.45+148
|
||||
YOSYS_VER := 0.45+153
|
||||
|
||||
# Note: We arrange for .gitcommit to contain the (short) commit hash in
|
||||
# tarballs generated with git-archive(1) using .gitattributes. The git repo
|
||||
|
@ -1009,16 +1009,17 @@ docs/source/cmd/abc.rst: $(TARGETS) $(EXTRA_TARGETS)
|
|||
./$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual'
|
||||
|
||||
PHONY: docs/gen_examples docs/gen_images docs/guidelines docs/usage docs/reqs
|
||||
docs/gen_examples:
|
||||
docs/gen_examples: $(TARGETS)
|
||||
$(Q) $(MAKE) -C docs examples
|
||||
|
||||
docs/gen_images:
|
||||
docs/gen_images: $(TARGETS)
|
||||
$(Q) $(MAKE) -C docs images
|
||||
|
||||
DOCS_GUIDELINE_FILES := GettingStarted CodingStyle
|
||||
docs/guidelines docs/source/generated:
|
||||
DOCS_GUIDELINE_SOURCE := $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES))
|
||||
docs/guidelines docs/source/generated: $(DOCS_GUIDELINE_SOURCE)
|
||||
$(Q) mkdir -p docs/source/generated
|
||||
$(Q) cp -f $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES)) docs/source/generated
|
||||
$(Q) cp -f $(DOCS_GUIDELINE_SOURCE) docs/source/generated
|
||||
|
||||
# some commands return an error and print the usage text to stderr
|
||||
define DOC_USAGE_STDERR
|
||||
|
|
2
abc
2
abc
|
@ -1 +1 @@
|
|||
Subproject commit 2188bc71228b0788569d83ad2b7e7b91ca5dcc09
|
||||
Subproject commit cac8f99eaa220a5e3db5caeb87cef0a975c953a2
|
1
backends/aiger2/Makefile.inc
Normal file
1
backends/aiger2/Makefile.inc
Normal file
|
@ -0,0 +1 @@
|
|||
OBJS += backends/aiger2/aiger.o
|
1471
backends/aiger2/aiger.cc
Normal file
1471
backends/aiger2/aiger.cc
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
all: examples all_tex tidy
|
||||
all: examples all_tex
|
||||
|
||||
# set a fake time in pdf generation to prevent unnecessary differences in output
|
||||
FAKETIME := TZ='Z' faketime -f '2022-01-01 00:00:00 x0,001'
|
||||
|
|
2
frontends/aiger2/Makefile.inc
Normal file
2
frontends/aiger2/Makefile.inc
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
OBJS += frontends/aiger2/xaiger.o
|
473
frontends/aiger2/xaiger.cc
Normal file
473
frontends/aiger2/xaiger.cc
Normal file
|
@ -0,0 +1,473 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) Martin Povišer <povik@cutebit.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kernel/register.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
uint32_t read_be32(std::istream &f) {
|
||||
return ((uint32_t) f.get() << 24) |
|
||||
((uint32_t) f.get() << 16) |
|
||||
((uint32_t) f.get() << 8) | (uint32_t) f.get();
|
||||
}
|
||||
|
||||
IdString read_idstring(std::istream &f)
|
||||
{
|
||||
std::string str;
|
||||
std::getline(f, str, '\0');
|
||||
if (!f.good())
|
||||
log_error("failed to read string\n");
|
||||
return RTLIL::escape_id(str);
|
||||
}
|
||||
|
||||
struct Xaiger2Frontend : public Frontend {
|
||||
Xaiger2Frontend() : Frontend("xaiger2", "(experimental) read XAIGER file")
|
||||
{
|
||||
experimental();
|
||||
}
|
||||
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" read_xaiger2 -sc_mapping [options] <filename>\n");
|
||||
log("\n");
|
||||
log("Read a standard cell mapping from a XAIGER file into an existing module.\n");
|
||||
log("\n");
|
||||
log(" -module_name <name>\n");
|
||||
log(" name of the target module\n");
|
||||
log("\n");
|
||||
log(" -map2 <filename>\n");
|
||||
log(" read file with symbol information\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void read_sc_mapping(std::istream *&f, std::string filename, std::vector<std::string> args, Design *design)
|
||||
{
|
||||
IdString module_name;
|
||||
std::string map_filename;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 2; argidx < args.size(); argidx++) {
|
||||
std::string arg = args[argidx];
|
||||
if (arg == "-module_name" && argidx + 1 < args.size()) {
|
||||
module_name = RTLIL::escape_id(args[++argidx]);
|
||||
continue;
|
||||
}
|
||||
if (arg == "-map2" && argidx + 1 < args.size()) {
|
||||
map_filename = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx, true);
|
||||
|
||||
if (map_filename.empty())
|
||||
log_error("A '-map2' argument required\n");
|
||||
if (module_name.empty())
|
||||
log_error("A '-module_name' argument required\n");
|
||||
|
||||
Module *module = design->module(module_name);
|
||||
if (!module)
|
||||
log_error("Module '%s' not found\n", log_id(module_name));
|
||||
|
||||
std::ifstream map_file;
|
||||
map_file.open(map_filename);
|
||||
if (!map_file)
|
||||
log_error("Failed to open map file '%s'\n", map_filename.c_str());
|
||||
|
||||
unsigned int M, I, L, O, A;
|
||||
std::string header;
|
||||
if (!(*f >> header >> M >> I >> L >> O >> A) || header != "aig")
|
||||
log_error("Bad header\n");
|
||||
std::string line;
|
||||
std::getline(*f, line);
|
||||
log_debug("M=%u I=%u L=%u O=%u A=%u\n", M, I, L, O, A);
|
||||
|
||||
if (L != 0)
|
||||
log_error("Latches unsupported\n");
|
||||
if (I + L + A != M)
|
||||
log_error("Inconsistent header\n");
|
||||
|
||||
std::vector<int> outputs;
|
||||
for (int i = 0; i < (int) O; i++) {
|
||||
int po;
|
||||
*f >> po;
|
||||
log_assert(f->get() == '\n');
|
||||
outputs.push_back(po);
|
||||
}
|
||||
|
||||
std::vector<std::pair<Cell *, Module *>> boxes;
|
||||
std::vector<bool> retained_boxes;
|
||||
std::vector<SigBit> bits(2 + 2*M, RTLIL::Sm);
|
||||
bits[0] = RTLIL::S0;
|
||||
bits[1] = RTLIL::S1;
|
||||
|
||||
std::string type;
|
||||
while (map_file >> type) {
|
||||
if (type == "pi") {
|
||||
int pi_idx;
|
||||
int woffset;
|
||||
std::string name;
|
||||
if (!(map_file >> pi_idx >> woffset >> name))
|
||||
log_error("Bad map file (1)\n");
|
||||
int lit = (2 * pi_idx) + 2;
|
||||
if (lit < 0 || lit >= (int) bits.size())
|
||||
log_error("Bad map file (2)\n");
|
||||
Wire *w = module->wire(name);
|
||||
if (!w || woffset < 0 || woffset >= w->width)
|
||||
log_error("Map file references non-existent signal bit %s[%d]\n",
|
||||
name.c_str(), woffset);
|
||||
bits[lit] = SigBit(w, woffset);
|
||||
} else if (type == "box") {
|
||||
int box_seq;
|
||||
std::string name;
|
||||
if (!(map_file >> box_seq >> name))
|
||||
log_error("Bad map file (20)\n");
|
||||
if (box_seq < 0)
|
||||
log_error("Bad map file (21)\n");
|
||||
|
||||
Cell *box = module->cell(RTLIL::escape_id(name));
|
||||
if (!box)
|
||||
log_error("Map file references non-existent box %s\n",
|
||||
name.c_str());
|
||||
|
||||
Module *def = design->module(box->type);
|
||||
if (def && !box->parameters.empty()) {
|
||||
// TODO: This is potentially costly even if a cached derivation exists
|
||||
def = design->module(def->derive(design, box->parameters));
|
||||
log_assert(def);
|
||||
}
|
||||
|
||||
if (!def)
|
||||
log_error("Bad map file (22)\n");
|
||||
|
||||
if (box_seq >= (int) boxes.size()) {
|
||||
boxes.resize(box_seq + 1);
|
||||
retained_boxes.resize(box_seq + 1);
|
||||
}
|
||||
boxes[box_seq] = std::make_pair(box, def);
|
||||
} else {
|
||||
std::string scratch;
|
||||
std::getline(map_file, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int) A; i++) {
|
||||
while (f->get() & 0x80 && !f->eof());
|
||||
while (f->get() & 0x80 && !f->eof());
|
||||
}
|
||||
|
||||
if (f->get() != 'c')
|
||||
log_error("Missing 'c' ahead of extensions\n");
|
||||
if (f->peek() == '\n')
|
||||
f->get();
|
||||
auto extensions_start = f->tellg();
|
||||
|
||||
log_debug("reading 'h' (first pass)\n");
|
||||
for (int c = f->get(); c != EOF; c = f->get()) {
|
||||
if (c == 'h') {
|
||||
uint32_t len, ci_num, co_num, pi_num, po_num, no_boxes;
|
||||
len = read_be32(*f);
|
||||
read_be32(*f);
|
||||
ci_num = read_be32(*f);
|
||||
co_num = read_be32(*f);
|
||||
pi_num = read_be32(*f);
|
||||
po_num = read_be32(*f);
|
||||
no_boxes = read_be32(*f);
|
||||
|
||||
log_debug("len=%u ci_num=%u co_num=%u pi_num=%u po_nun=%u no_boxes=%u\n",
|
||||
len, ci_num, co_num, pi_num, po_num, no_boxes);
|
||||
|
||||
int ci_counter = 0;
|
||||
for (uint32_t i = 0; i < no_boxes; i++) {
|
||||
uint32_t box_inputs, box_outputs, box_id, box_seq;
|
||||
box_inputs = read_be32(*f);
|
||||
box_outputs = read_be32(*f);
|
||||
box_id = read_be32(*f);
|
||||
box_seq = read_be32(*f);
|
||||
|
||||
log("box_seq=%d boxes.size=%d\n", box_seq, (int) boxes.size());
|
||||
log_assert(box_seq < boxes.size());
|
||||
|
||||
auto [cell, def] = boxes[box_seq];
|
||||
log_assert(cell && def);
|
||||
retained_boxes[box_seq] = true;
|
||||
|
||||
int box_ci_idx = 0;
|
||||
for (auto port_id : def->ports) {
|
||||
Wire *port = def->wire(port_id);
|
||||
if (port->port_output) {
|
||||
if (!cell->hasPort(port_id) || cell->getPort(port_id).size() != port->width)
|
||||
log_error("Malformed design (1)\n");
|
||||
|
||||
SigSpec &conn = cell->connections_[port_id];
|
||||
for (int j = 0; j < port->width; j++) {
|
||||
if (conn[j].wire && conn[j].wire->port_output)
|
||||
conn[j] = module->addWire(module->uniquify(
|
||||
stringf("$box$%s$%s$%d",
|
||||
cell->name.isPublic() ? cell->name.c_str() + 1 : cell->name.c_str(),
|
||||
port_id.isPublic() ? port_id.c_str() + 1 : port_id.c_str(),
|
||||
j)));
|
||||
|
||||
bits[2*(pi_num + ci_counter + box_ci_idx++) + 2] = conn[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_assert(box_ci_idx == (int) box_outputs);
|
||||
ci_counter += box_ci_idx;
|
||||
}
|
||||
log_assert(pi_num + ci_counter == ci_num);
|
||||
} else if (c == '\n') {
|
||||
break;
|
||||
} else if (c == 'c') {
|
||||
break;
|
||||
} else {
|
||||
uint32_t len = read_be32(*f);
|
||||
f->ignore(len);
|
||||
log_debug(" section '%c' (%d): ignoring %d bytes\n", c, c, len);
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("reading 'M' (second pass)\n");
|
||||
|
||||
f->seekg(extensions_start);
|
||||
bool read_mapping = false;
|
||||
uint32_t no_cells, no_instances;
|
||||
for (int c = f->get(); c != EOF; c = f->get()) {
|
||||
if (c == 'M') {
|
||||
uint32_t len = read_be32(*f);
|
||||
read_mapping = true;
|
||||
|
||||
no_cells = read_be32(*f);
|
||||
no_instances = read_be32(*f);
|
||||
|
||||
log_debug("M: len=%u no_cells=%u no_instances=%u\n", len, no_cells, no_instances);
|
||||
|
||||
struct MappingCell {
|
||||
RTLIL::IdString type;
|
||||
RTLIL::IdString out;
|
||||
std::vector<RTLIL::IdString> ins;
|
||||
};
|
||||
std::vector<MappingCell> cells;
|
||||
cells.resize(no_cells);
|
||||
|
||||
for (unsigned i = 0; i < no_cells; ++i) {
|
||||
auto &cell = cells[i];
|
||||
cell.type = read_idstring(*f);
|
||||
cell.out = read_idstring(*f);
|
||||
uint32_t nins = read_be32(*f);
|
||||
for (uint32_t j = 0; j < nins; j++)
|
||||
cell.ins.push_back(read_idstring(*f));
|
||||
log_debug("M: Cell %s (out %s, ins", log_id(cell.type), log_id(cell.out));
|
||||
for (auto in : cell.ins)
|
||||
log_debug(" %s", log_id(in));
|
||||
log_debug(")\n");
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < no_instances; ++i) {
|
||||
uint32_t cell_id = read_be32(*f);
|
||||
uint32_t out_lit = read_be32(*f);
|
||||
|
||||
log_assert(out_lit < bits.size());
|
||||
log_assert(bits[out_lit] == RTLIL::Sm);
|
||||
log_assert(cell_id < cells.size());
|
||||
auto &cell = cells[cell_id];
|
||||
Cell *instance = module->addCell(module->uniquify(stringf("$sc%d", out_lit)), cell.type);
|
||||
auto out_w = module->addWire(module->uniquify(stringf("$lit%d", out_lit)));
|
||||
instance->setPort(cell.out, out_w);
|
||||
bits[out_lit] = out_w;
|
||||
for (auto in : cell.ins) {
|
||||
uint32_t in_lit = read_be32(*f);
|
||||
log_assert(out_lit < bits.size());
|
||||
log_assert(bits[in_lit] != RTLIL::Sm);
|
||||
instance->setPort(in, bits[in_lit]);
|
||||
}
|
||||
}
|
||||
} else if (c == '\n') {
|
||||
break;
|
||||
} else if (c == 'c') {
|
||||
break;
|
||||
} else {
|
||||
uint32_t len = read_be32(*f);
|
||||
f->ignore(len);
|
||||
log_debug(" section '%c' (%d): ignoring %d bytes\n", c, c, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (!read_mapping)
|
||||
log_error("Missing mapping (no 'M' section)\n");
|
||||
|
||||
log("Read %d instances with cell library of size %d.\n",
|
||||
no_instances, no_cells);
|
||||
|
||||
f->seekg(extensions_start);
|
||||
log_debug("reading 'h' (second pass)\n");
|
||||
int co_counter = 0;
|
||||
for (int c = f->get(); c != EOF; c = f->get()) {
|
||||
if (c == 'h') {
|
||||
uint32_t len, ci_num, co_num, pi_num, po_num, no_boxes;
|
||||
len = read_be32(*f);
|
||||
read_be32(*f);
|
||||
ci_num = read_be32(*f);
|
||||
co_num = read_be32(*f);
|
||||
pi_num = read_be32(*f);
|
||||
po_num = read_be32(*f);
|
||||
no_boxes = read_be32(*f);
|
||||
|
||||
log_debug("len=%u ci_num=%u co_num=%u pi_num=%u po_nun=%u no_boxes=%u\n",
|
||||
len, ci_num, co_num, pi_num, po_num, no_boxes);
|
||||
|
||||
for (uint32_t i = 0; i < no_boxes; i++) {
|
||||
uint32_t box_inputs, box_outputs, box_id, box_seq;
|
||||
box_inputs = read_be32(*f);
|
||||
box_outputs = read_be32(*f);
|
||||
box_id = read_be32(*f);
|
||||
box_seq = read_be32(*f);
|
||||
|
||||
log("box_seq=%d boxes.size=%d\n", box_seq, (int) boxes.size());
|
||||
log_assert(box_seq < boxes.size());
|
||||
|
||||
auto [cell, def] = boxes[box_seq];
|
||||
log_assert(cell && def);
|
||||
|
||||
int box_co_idx = 0;
|
||||
for (auto port_id : def->ports) {
|
||||
Wire *port = def->wire(port_id);
|
||||
SigSpec conn;
|
||||
if (port->port_input) {
|
||||
if (!cell->hasPort(port_id) || cell->getPort(port_id).size() != port->width)
|
||||
log_error("Malformed design (2)\n");
|
||||
|
||||
SigSpec conn;
|
||||
for (int j = 0; j < port->width; j++) {
|
||||
log_assert(co_counter + box_co_idx < (int) outputs.size());
|
||||
int lit = outputs[co_counter + box_co_idx++];
|
||||
log_assert(lit >= 0 && lit < (int) bits.size());
|
||||
SigBit bit = bits[lit];
|
||||
if (bit == RTLIL::Sm)
|
||||
log_error("Malformed mapping (1)\n");
|
||||
conn.append(bit);
|
||||
}
|
||||
cell->setPort(port_id, conn);
|
||||
}
|
||||
}
|
||||
|
||||
log_assert(box_co_idx == (int) box_inputs);
|
||||
co_counter += box_co_idx;
|
||||
}
|
||||
log_assert(po_num + co_counter == co_num);
|
||||
} else if (c == '\n') {
|
||||
break;
|
||||
} else if (c == 'c') {
|
||||
break;
|
||||
} else {
|
||||
uint32_t len = read_be32(*f);
|
||||
f->ignore(len);
|
||||
log_debug(" section '%c' (%d): ignoring %d bytes\n", c, c, len);
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
std::string scratch;
|
||||
std::getline(*f, scratch);
|
||||
if (f->eof())
|
||||
break;
|
||||
log_assert(!f->fail());
|
||||
log("input file: %s\n", scratch.c_str());
|
||||
}
|
||||
|
||||
log_debug("co_counter=%d\n", co_counter);
|
||||
|
||||
// TODO: seek without close/open
|
||||
map_file.close();
|
||||
map_file.open(map_filename);
|
||||
while (map_file >> type) {
|
||||
if (type == "po") {
|
||||
int po_idx;
|
||||
int woffset;
|
||||
std::string name;
|
||||
if (!(map_file >> po_idx >> woffset >> name))
|
||||
log_error("Bad map file (3)\n");
|
||||
po_idx += co_counter;
|
||||
if (po_idx < 0 || po_idx >= (int) outputs.size())
|
||||
log_error("Bad map file (4)\n");
|
||||
int lit = outputs[po_idx];
|
||||
if (lit < 0 || lit >= (int) bits.size())
|
||||
log_error("Bad map file (5)\n");
|
||||
if (bits[lit] == RTLIL::Sm)
|
||||
log_error("Bad map file (6)\n");
|
||||
Wire *w = module->wire(name);
|
||||
if (!w || woffset < 0 || woffset >= w->width)
|
||||
log_error("Map file references non-existent signal bit %s[%d]\n",
|
||||
name.c_str(), woffset);
|
||||
module->connect(SigBit(w, woffset), bits[lit]);
|
||||
} else if (type == "pseudopo") {
|
||||
int po_idx;
|
||||
int poffset;
|
||||
std::string box_name;
|
||||
std::string box_port;
|
||||
if (!(map_file >> po_idx >> poffset >> box_name >> box_port))
|
||||
log_error("Bad map file (7)\n");
|
||||
po_idx += co_counter;
|
||||
if (po_idx < 0 || po_idx >= (int) outputs.size())
|
||||
log_error("Bad map file (8)\n");
|
||||
int lit = outputs[po_idx];
|
||||
if (lit < 0 || lit >= (int) bits.size())
|
||||
log_error("Bad map file (9)\n");
|
||||
if (bits[lit] == RTLIL::Sm)
|
||||
log_error("Bad map file (10)\n");
|
||||
Cell *cell = module->cell(box_name);
|
||||
if (!cell || !cell->hasPort(box_port))
|
||||
log_error("Map file references non-existent box port %s/%s\n",
|
||||
box_name.c_str(), box_port.c_str());
|
||||
SigSpec &port = cell->connections_[box_port];
|
||||
if (poffset < 0 || poffset >= port.size())
|
||||
log_error("Map file references non-existent box port bit %s/%s[%d]\n",
|
||||
box_name.c_str(), box_port.c_str(), poffset);
|
||||
port[poffset] = bits[lit];
|
||||
} else {
|
||||
std::string scratch;
|
||||
std::getline(map_file, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
int box_seq = 0;
|
||||
for (auto [cell, def] : boxes) {
|
||||
if (!retained_boxes[box_seq++])
|
||||
module->remove(cell);
|
||||
}
|
||||
}
|
||||
|
||||
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, Design *design) override
|
||||
{
|
||||
log_header(design, "Executing XAIGER2 frontend.\n");
|
||||
|
||||
if (args.size() > 1 && args[1] == "-sc_mapping") {
|
||||
read_sc_mapping(f, filename, args, design);
|
||||
return;
|
||||
}
|
||||
|
||||
log_cmd_error("Mode '-sc_mapping' must be selected\n");
|
||||
}
|
||||
} Xaiger2Frontend;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -465,6 +465,9 @@ struct LibertyFrontend : public Frontend {
|
|||
log(" -setattr <attribute_name>\n");
|
||||
log(" set the specified attribute (to the value 1) on all loaded modules\n");
|
||||
log("\n");
|
||||
log(" -unit_delay\n");
|
||||
log(" import combinational timing arcs under the unit delay model\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
|
@ -475,6 +478,7 @@ struct LibertyFrontend : public Frontend {
|
|||
bool flag_ignore_miss_func = false;
|
||||
bool flag_ignore_miss_dir = false;
|
||||
bool flag_ignore_miss_data_latch = false;
|
||||
bool flag_unit_delay = false;
|
||||
std::vector<std::string> attributes;
|
||||
|
||||
size_t argidx;
|
||||
|
@ -514,6 +518,10 @@ struct LibertyFrontend : public Frontend {
|
|||
attributes.push_back(RTLIL::escape_id(args[++argidx]));
|
||||
continue;
|
||||
}
|
||||
if (arg == "-unit_delay") {
|
||||
flag_unit_delay = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
@ -710,6 +718,7 @@ struct LibertyFrontend : public Frontend {
|
|||
continue;
|
||||
|
||||
RTLIL::Wire *wire = module->wires_.at(RTLIL::escape_id(node->args.at(0)));
|
||||
log_assert(wire);
|
||||
|
||||
if (dir && dir->value == "inout") {
|
||||
wire->port_input = true;
|
||||
|
@ -748,6 +757,43 @@ struct LibertyFrontend : public Frontend {
|
|||
}
|
||||
module->connect(RTLIL::SigSig(wire, out_sig));
|
||||
}
|
||||
|
||||
if (flag_unit_delay) {
|
||||
pool<Wire *> done;
|
||||
|
||||
for (auto timing : node->children)
|
||||
if (timing->id == "timing" && timing->args.empty()) {
|
||||
auto type = timing->find("timing_type");
|
||||
auto related_pin = timing->find("related_pin");
|
||||
if (!type || type->value != "combinational" || !related_pin)
|
||||
continue;
|
||||
|
||||
Wire *related = module->wire(RTLIL::escape_id(related_pin->value));
|
||||
if (!related)
|
||||
log_error("Failed to find related pin %s for timing of pin %s on %s\n",
|
||||
related_pin->value.c_str(), log_id(wire), log_id(module));
|
||||
|
||||
if (done.count(related))
|
||||
continue;
|
||||
|
||||
RTLIL::Cell *spec = module->addCell(NEW_ID, ID($specify2));
|
||||
spec->setParam(ID::SRC_WIDTH, 1);
|
||||
spec->setParam(ID::DST_WIDTH, 1);
|
||||
spec->setParam(ID::T_FALL_MAX, 1000);
|
||||
spec->setParam(ID::T_FALL_TYP, 1000);
|
||||
spec->setParam(ID::T_FALL_MIN, 1000);
|
||||
spec->setParam(ID::T_RISE_MAX, 1000);
|
||||
spec->setParam(ID::T_RISE_TYP, 1000);
|
||||
spec->setParam(ID::T_RISE_MIN, 1000);
|
||||
spec->setParam(ID::SRC_DST_POL, false);
|
||||
spec->setParam(ID::SRC_DST_PEN, false);
|
||||
spec->setParam(ID::FULL, false);
|
||||
spec->setPort(ID::EN, Const(1, 1));
|
||||
spec->setPort(ID::SRC, related);
|
||||
spec->setPort(ID::DST, wire);
|
||||
done.insert(related);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -381,11 +381,10 @@ struct CellTypes
|
|||
HANDLE_CELL_TYPE(modfloor)
|
||||
HANDLE_CELL_TYPE(pow)
|
||||
HANDLE_CELL_TYPE(pos)
|
||||
HANDLE_CELL_TYPE(buf)
|
||||
HANDLE_CELL_TYPE(neg)
|
||||
#undef HANDLE_CELL_TYPE
|
||||
|
||||
if (type == ID($_BUF_))
|
||||
if (type.in(ID($_BUF_), ID($buf)))
|
||||
return arg1;
|
||||
if (type == ID($_NOT_))
|
||||
return eval_not(arg1);
|
||||
|
|
|
@ -241,6 +241,7 @@ int main(int argc, char **argv)
|
|||
std::string topmodule = "";
|
||||
std::string perffile = "";
|
||||
bool scriptfile_tcl = false;
|
||||
bool scriptfile_python = false;
|
||||
bool print_banner = true;
|
||||
bool print_stats = true;
|
||||
bool call_abort = false;
|
||||
|
@ -304,7 +305,12 @@ int main(int argc, char **argv)
|
|||
printf(" execute the commands in the tcl script file (see 'help tcl' for details)\n");
|
||||
printf("\n");
|
||||
printf(" -C\n");
|
||||
printf(" enters TCL interatcive shell mode\n");
|
||||
printf(" enters TCL interactive shell mode\n");
|
||||
#endif
|
||||
#ifdef WITH_PYTHON
|
||||
printf("\n");
|
||||
printf(" -y python_scriptfile\n");
|
||||
printf(" execute a python script with libyosys available as a built-in module\n");
|
||||
#endif
|
||||
printf("\n");
|
||||
printf(" -p command\n");
|
||||
|
@ -379,7 +385,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "MXAQTVCSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:r:D:P:E:x:B:")) != -1)
|
||||
while ((opt = getopt(argc, argv, "MXAQTVCSgm:f:Hh:b:o:p:l:L:qv:tds:c:y:W:w:e:r:D:P:E:x:B:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
@ -464,11 +470,19 @@ int main(int argc, char **argv)
|
|||
case 's':
|
||||
scriptfile = optarg;
|
||||
scriptfile_tcl = false;
|
||||
scriptfile_python = false;
|
||||
run_shell = false;
|
||||
break;
|
||||
case 'c':
|
||||
scriptfile = optarg;
|
||||
scriptfile_tcl = true;
|
||||
scriptfile_python = false;
|
||||
run_shell = false;
|
||||
break;
|
||||
case 'y':
|
||||
scriptfile = optarg;
|
||||
scriptfile_tcl = false;
|
||||
scriptfile_python = true;
|
||||
run_shell = false;
|
||||
break;
|
||||
case 'W':
|
||||
|
@ -607,8 +621,9 @@ int main(int argc, char **argv)
|
|||
run_pass(vdef_cmd);
|
||||
}
|
||||
|
||||
if (scriptfile.empty() || !scriptfile_tcl) {
|
||||
// Without a TCL script, arguments following '--' are also treated as frontend files
|
||||
if (scriptfile.empty() || (!scriptfile_tcl && !scriptfile_python)) {
|
||||
// Without a TCL or Python script, arguments following '--' are also
|
||||
// treated as frontend files
|
||||
for (int i = optind; i < argc; ++i)
|
||||
frontend_files.push_back(argv[i]);
|
||||
}
|
||||
|
@ -636,7 +651,36 @@ int main(int argc, char **argv)
|
|||
if (Tcl_EvalFile(interp, scriptfile.c_str()) != TCL_OK)
|
||||
log_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(yosys_get_tcl_interp()));
|
||||
#else
|
||||
log_error("Can't exectue TCL script: this version of yosys is not built with TCL support enabled.\n");
|
||||
log_error("Can't execute TCL script: this version of yosys is not built with TCL support enabled.\n");
|
||||
#endif
|
||||
} else if (scriptfile_python) {
|
||||
#ifdef WITH_PYTHON
|
||||
PyObject *sys = PyImport_ImportModule("sys");
|
||||
PyObject *new_argv = PyList_New(argc - optind + 1);
|
||||
PyList_SetItem(new_argv, 0, PyUnicode_FromString(scriptfile.c_str()));
|
||||
for (int i = optind; i < argc; ++i)
|
||||
PyList_SetItem(new_argv, i - optind + 1, PyUnicode_FromString(argv[i]));
|
||||
|
||||
PyObject *old_argv = PyObject_GetAttrString(sys, "argv");
|
||||
PyObject_SetAttrString(sys, "argv", new_argv);
|
||||
Py_DECREF(old_argv);
|
||||
|
||||
PyObject *py_path = PyUnicode_FromString(scriptfile.c_str());
|
||||
PyObject_SetAttrString(sys, "_yosys_script_path", py_path);
|
||||
Py_DECREF(py_path);
|
||||
PyRun_SimpleString("import os, sys; sys.path.insert(0, os.path.dirname(os.path.abspath(sys._yosys_script_path)))");
|
||||
|
||||
FILE *scriptfp = fopen(scriptfile.c_str(), "r");
|
||||
if (scriptfp == nullptr) {
|
||||
log_error("Failed to open file '%s' for reading.\n", scriptfile.c_str());
|
||||
}
|
||||
if (PyRun_SimpleFile(scriptfp, scriptfile.c_str()) != 0) {
|
||||
log_flush();
|
||||
PyErr_Print();
|
||||
log_error("Python interpreter encountered an exception.");
|
||||
}
|
||||
#else
|
||||
log_error("Can't execute Python script: this version of yosys is not built with Python support enabled.\n");
|
||||
#endif
|
||||
} else
|
||||
run_frontend(scriptfile, "script");
|
||||
|
|
|
@ -459,8 +459,21 @@ void log_cmd_error(const char *format, ...)
|
|||
|
||||
if (log_cmd_error_throw) {
|
||||
log_last_error = vstringf(format, ap);
|
||||
|
||||
// Make sure the error message gets through any selective silencing
|
||||
// of log output
|
||||
bool pop_errfile = false;
|
||||
if (log_errfile != NULL) {
|
||||
log_files.push_back(log_errfile);
|
||||
pop_errfile = true;
|
||||
}
|
||||
|
||||
log("ERROR: %s", log_last_error.c_str());
|
||||
log_flush();
|
||||
|
||||
if (pop_errfile)
|
||||
log_files.pop_back();
|
||||
|
||||
throw log_cmd_error_exception();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,12 @@ OBJS += passes/techmap/abc.o
|
|||
OBJS += passes/techmap/abc9.o
|
||||
OBJS += passes/techmap/abc9_exe.o
|
||||
OBJS += passes/techmap/abc9_ops.o
|
||||
OBJS += passes/techmap/abc_new.o
|
||||
ifneq ($(ABCEXTERNAL),)
|
||||
passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
|
||||
passes/techmap/abc9.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
|
||||
passes/techmap/abc9_exe.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
|
||||
passes/techmap/abc_new.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -220,7 +220,8 @@ struct Abc9Pass : public ScriptPass
|
|||
std::string arg = args[argidx];
|
||||
if ((arg == "-exe" || arg == "-script" || arg == "-D" ||
|
||||
/*arg == "-S" ||*/ arg == "-lut" || arg == "-luts" ||
|
||||
/*arg == "-box" ||*/ arg == "-W") &&
|
||||
/*arg == "-box" ||*/ arg == "-W" || arg == "-genlib" ||
|
||||
arg == "-constr" || arg == "-dont_use" || arg == "-liberty") &&
|
||||
argidx+1 < args.size()) {
|
||||
if (arg == "-lut" || arg == "-luts")
|
||||
lut_mode = true;
|
||||
|
|
|
@ -167,8 +167,8 @@ struct abc9_output_filter
|
|||
void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe_file,
|
||||
vector<int> lut_costs, bool dff_mode, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
|
||||
bool show_tempdir, std::string box_file, std::string lut_file,
|
||||
std::string wire_delay, std::string tempdir_name
|
||||
)
|
||||
std::vector<std::string> liberty_files, std::string wire_delay, std::string tempdir_name,
|
||||
std::string constr_file, std::vector<std::string> dont_use_cells)
|
||||
{
|
||||
std::string abc9_script;
|
||||
|
||||
|
@ -176,8 +176,17 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
|
|||
abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
|
||||
else if (!lut_file.empty())
|
||||
abc9_script += stringf("read_lut \"%s\"; ", lut_file.c_str());
|
||||
else
|
||||
log_abort();
|
||||
else if (!liberty_files.empty()) {
|
||||
std::string dont_use_args;
|
||||
for (std::string dont_use_cell : dont_use_cells) {
|
||||
dont_use_args += stringf("-X \"%s\" ", dont_use_cell.c_str());
|
||||
}
|
||||
for (std::string liberty_file : liberty_files) {
|
||||
abc9_script += stringf("read_lib %s -w \"%s\" ; ", dont_use_args.c_str(), liberty_file.c_str());
|
||||
}
|
||||
if (!constr_file.empty())
|
||||
abc9_script += stringf("read_constr -v \"%s\"; ", constr_file.c_str());
|
||||
}
|
||||
|
||||
log_assert(!box_file.empty());
|
||||
abc9_script += stringf("read_box \"%s\"; ", box_file.c_str());
|
||||
|
@ -359,6 +368,26 @@ struct Abc9ExePass : public Pass {
|
|||
log(" of output quality):\n");
|
||||
log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)).c_str());
|
||||
log("\n");
|
||||
log(" -constr <file>\n");
|
||||
log(" pass this file with timing constraints to ABC.\n");
|
||||
log(" use with -liberty.\n");
|
||||
log("\n");
|
||||
log(" a constr file contains two lines:\n");
|
||||
log(" set_driving_cell <cell_name>\n");
|
||||
log(" set_load <floating_point_number>\n");
|
||||
log("\n");
|
||||
log(" the set_driving_cell statement defines which cell type is assumed to\n");
|
||||
log(" drive the primary inputs and the set_load statement sets the load in\n");
|
||||
log(" femtofarads for each primary output.\n");
|
||||
log("\n");
|
||||
log(" -liberty <file>\n");
|
||||
log(" read the given Liberty file as a description of the target cell library.\n");
|
||||
log(" this option can be used multiple times.\n");
|
||||
log("\n");
|
||||
log(" -dont_use <cell_name>\n");
|
||||
log(" avoid usage of the technology cell <cell_name> when mapping the design.\n");
|
||||
log(" this option can be used multiple times.\n");
|
||||
log("\n");
|
||||
log(" -D <picoseconds>\n");
|
||||
log(" set delay target. the string {D} in the default scripts above is\n");
|
||||
log(" replaced by this option when used, and an empty string otherwise\n");
|
||||
|
@ -411,7 +440,8 @@ struct Abc9ExePass : public Pass {
|
|||
log_header(design, "Executing ABC9_EXE pass (technology mapping using ABC9).\n");
|
||||
|
||||
std::string exe_file = yosys_abc_executable;
|
||||
std::string script_file, clk_str, box_file, lut_file;
|
||||
std::string script_file, clk_str, box_file, lut_file, constr_file;
|
||||
std::vector<std::string> liberty_files, dont_use_cells;
|
||||
std::string delay_target, lutin_shared = "-S 1", wire_delay;
|
||||
std::string tempdir_name;
|
||||
bool fast_mode = false, dff_mode = false;
|
||||
|
@ -499,6 +529,18 @@ struct Abc9ExePass : public Pass {
|
|||
tempdir_name = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (arg == "-liberty" && argidx+1 < args.size()) {
|
||||
liberty_files.push_back(args[++argidx]);
|
||||
continue;
|
||||
}
|
||||
if (arg == "-dont_use" && argidx+1 < args.size()) {
|
||||
dont_use_cells.push_back(args[++argidx]);
|
||||
continue;
|
||||
}
|
||||
if (arg == "-constr" && argidx+1 < args.size()) {
|
||||
constr_file = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -562,7 +604,8 @@ struct Abc9ExePass : public Pass {
|
|||
|
||||
abc9_module(design, script_file, exe_file, lut_costs, dff_mode,
|
||||
delay_target, lutin_shared, fast_mode, show_tempdir,
|
||||
box_file, lut_file, wire_delay, tempdir_name);
|
||||
box_file, lut_file, liberty_files, wire_delay, tempdir_name,
|
||||
constr_file, dont_use_cells);
|
||||
}
|
||||
} Abc9ExePass;
|
||||
|
||||
|
|
153
passes/techmap/abc_new.cc
Normal file
153
passes/techmap/abc_new.cc
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2024 Martin Povišer <povik@cutebit.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/rtlil.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct AbcNewPass : public ScriptPass {
|
||||
AbcNewPass() : ScriptPass("abc_new", "(experimental) use ABC for SC technology mapping (new)")
|
||||
{
|
||||
experimental();
|
||||
}
|
||||
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" abc_new [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This command uses the ABC tool [1] to optimize the current design and map it to\n");
|
||||
log("the target standard cell library.\n");
|
||||
log("\n");
|
||||
log(" -run <from_label>:<to_label>\n");
|
||||
log(" only run the commands between the labels (see below). an empty\n");
|
||||
log(" from label is synonymous to 'begin', and empty to label is\n");
|
||||
log(" synonymous to the end of the command list.\n");
|
||||
log("\n");
|
||||
log(" -exe <command>\n");
|
||||
log(" -script <file>\n");
|
||||
log(" -D <picoseconds>\n");
|
||||
log(" -constr <file>\n");
|
||||
log(" -dont_use <cell_name>\n");
|
||||
log(" -liberty <file>\n");
|
||||
log(" these options are passed on to the 'abc9_exe' command which invokes\n");
|
||||
log(" the ABC tool on individual modules of the design. please see\n");
|
||||
log(" 'help abc9_exe' for more details\n");
|
||||
log("\n");
|
||||
log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
|
||||
log("\n");
|
||||
help_script();
|
||||
log("\n");
|
||||
}
|
||||
|
||||
bool cleanup;
|
||||
std::string abc_exe_options;
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *d) override
|
||||
{
|
||||
std::string run_from, run_to;
|
||||
cleanup = true;
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-exe" || args[argidx] == "-script" ||
|
||||
args[argidx] == "-D" ||
|
||||
args[argidx] == "-constr" || args[argidx] == "-dont_use" ||
|
||||
args[argidx] == "-liberty") {
|
||||
abc_exe_options += " " + args[argidx] + " " + args[argidx + 1];
|
||||
argidx++;
|
||||
} else if (args[argidx] == "-run" && argidx + 1 < args.size()) {
|
||||
size_t pos = args[++argidx].find(':');
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
run_from = args[argidx].substr(0, pos);
|
||||
run_to = args[argidx].substr(pos + 1);
|
||||
} else if (args[argidx] == "-nocleanup") {
|
||||
cleanup = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
extra_args(args, argidx, d);
|
||||
|
||||
log_header(d, "Executing ABC_NEW pass.\n");
|
||||
log_push();
|
||||
run_script(d, run_from, run_to);
|
||||
log_pop();
|
||||
}
|
||||
|
||||
void script() override
|
||||
{
|
||||
if (check_label("check")) {
|
||||
run("abc9_ops -check");
|
||||
}
|
||||
|
||||
if (check_label("prep_boxes")) {
|
||||
run("box_derive");
|
||||
run("abc9_ops -prep_box");
|
||||
}
|
||||
|
||||
if (check_label("map")) {
|
||||
std::vector<Module *> selected_modules;
|
||||
|
||||
if (!help_mode) {
|
||||
selected_modules = active_design->selected_whole_modules_warn();
|
||||
active_design->selection_stack.emplace_back(false);
|
||||
} else {
|
||||
selected_modules = {nullptr};
|
||||
run("foreach module in selection");
|
||||
}
|
||||
|
||||
for (auto mod : selected_modules) {
|
||||
std::string tmpdir = "<abc-temp-dir>";
|
||||
std::string modname = "<module>";
|
||||
std::string exe_options = "[options]";
|
||||
if (!help_mode) {
|
||||
tmpdir = cleanup ? (get_base_tmpdir() + "/") : "_tmp_";
|
||||
tmpdir += proc_program_prefix() + "yosys-abc-XXXXXX";
|
||||
tmpdir = make_temp_dir(tmpdir);
|
||||
modname = mod->name.str();
|
||||
exe_options = abc_exe_options;
|
||||
log_header(active_design, "Mapping module '%s'.\n", log_id(mod));
|
||||
log_push();
|
||||
active_design->selection().select(mod);
|
||||
}
|
||||
|
||||
run(stringf(" abc9_ops -write_box %s/input.box", tmpdir.c_str()));
|
||||
run(stringf(" write_xaiger2 -mapping_prep -map2 %s/input.map2 %s/input.xaig", tmpdir.c_str(), tmpdir.c_str()));
|
||||
run(stringf(" abc9_exe %s -cwd %s -box %s/input.box", exe_options.c_str(), tmpdir.c_str(), tmpdir.c_str()));
|
||||
run(stringf(" read_xaiger2 -sc_mapping -module_name %s -map2 %s/input.map2 %s/output.aig",
|
||||
modname.c_str(), tmpdir.c_str(), tmpdir.c_str()));
|
||||
|
||||
if (!help_mode) {
|
||||
active_design->selection().selected_modules.clear();
|
||||
log_pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (!help_mode) {
|
||||
active_design->selection_stack.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
} AbcNewPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -70,9 +70,9 @@ struct BufnormPass : public Pass {
|
|||
log(" to chain 'keep' wires first, then ports in declaration order,\n");
|
||||
log(" and then the other wires in alphanumeric sort order.)\n");
|
||||
log("\n");
|
||||
log(" -noinit\n");
|
||||
log(" Do not move 'init' attributes to the wires on FF output ports.\n");
|
||||
log("\n");
|
||||
// log(" -noinit\n");
|
||||
// log(" Do not move 'init' attributes to the wires on FF output ports.\n");
|
||||
// log("\n");
|
||||
log("Run 'bufnorm' with -pos, -bits, or -conn on the whole design to remove all\n");
|
||||
log("$buf buffer cells and exit 'buffered-normalized mode' again.\n");
|
||||
log("\n");
|
||||
|
@ -108,7 +108,7 @@ struct BufnormPass : public Pass {
|
|||
bool nokeep_mode = false;
|
||||
bool nosticky_mode = false;
|
||||
bool alphasort_mode = false;
|
||||
bool noinit_mode = false; // FIXME: Actually move init attributes
|
||||
// bool noinit_mode = false; // FIXME: Actually move init attributes
|
||||
bool nomode_mode = false;
|
||||
|
||||
bool pos_mode = false;
|
||||
|
@ -169,11 +169,11 @@ struct BufnormPass : public Pass {
|
|||
got_non_update_reset_opt = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-noinit") {
|
||||
noinit_mode = true;
|
||||
got_non_update_reset_opt = true;
|
||||
continue;
|
||||
}
|
||||
// if (arg == "-noinit") {
|
||||
// noinit_mode = true;
|
||||
// got_non_update_reset_opt = true;
|
||||
// continue;
|
||||
// }
|
||||
if (arg == "-pos") {
|
||||
pos_mode = true;
|
||||
got_non_update_reset_opt = true;
|
||||
|
|
|
@ -304,6 +304,7 @@ endmodule
|
|||
// Divide and Modulo
|
||||
// --------------------------------------------------------
|
||||
|
||||
`ifndef NODIV
|
||||
module \$__div_mod_u (A, B, Y, R);
|
||||
parameter WIDTH = 1;
|
||||
|
||||
|
@ -531,7 +532,7 @@ module _90_modfloor (A, B, Y);
|
|||
.R(Y)
|
||||
);
|
||||
endmodule
|
||||
|
||||
`endif
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Power
|
||||
|
|
|
@ -266,7 +266,8 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
|
||||
if (check_label("map_gates")) {
|
||||
if (inferAdder && family == "qlf_k6n10f") {
|
||||
run("techmap -map +/techmap.v -map " + lib_path + family + "/arith_map.v", "(unless -no_adder)");
|
||||
run("techmap -map +/techmap.v -map " + lib_path + family + "/arith_map.v -D NODIV", "(unless -no_adder)");
|
||||
run("techmap", "(unless -no_adder)");
|
||||
} else {
|
||||
run("techmap");
|
||||
}
|
||||
|
|
14
tests/arch/quicklogic/qlf_k6n10f/div.ys
Normal file
14
tests/arch/quicklogic/qlf_k6n10f/div.ys
Normal file
|
@ -0,0 +1,14 @@
|
|||
# division by constants should not infer carry chains.
|
||||
read_verilog <<EOF
|
||||
|
||||
module top (input [15:0] a, output [15:0] y);
|
||||
assign y = a / 3;
|
||||
endmodule
|
||||
|
||||
EOF
|
||||
|
||||
equiv_opt -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v synth_quicklogic -family qlf_k6n10f
|
||||
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
||||
cd top # Constrain all select calls below inside the top module
|
||||
select -assert-max 100 t:$lut
|
||||
select -assert-none t:$lut %% t:* %D
|
1
tests/liberty/.gitignore
vendored
1
tests/liberty/.gitignore
vendored
|
@ -1,4 +1,3 @@
|
|||
*.log
|
||||
test.ys
|
||||
*.filtered
|
||||
*.verilogsim
|
||||
|
|
|
@ -3,11 +3,13 @@ set -e
|
|||
|
||||
for x in *.lib; do
|
||||
echo "Testing on $x.."
|
||||
echo "read_verilog small.v" > test.ys
|
||||
echo "synth -top small" >> test.ys
|
||||
echo "dfflibmap -info -liberty ${x}" >> test.ys
|
||||
../../yosys -ql ${x%.lib}.log -s test.ys
|
||||
../../yosys -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty ${x}" -ql ${x%.lib}.log
|
||||
../../yosys-filterlib - $x 2>/dev/null > $x.filtered
|
||||
../../yosys-filterlib -verilogsim $x > $x.verilogsim
|
||||
diff $x.filtered $x.filtered.ok && diff $x.verilogsim $x.verilogsim.ok
|
||||
done
|
||||
|
||||
for x in *.ys; do
|
||||
echo "Running $x.."
|
||||
../../yosys -q -s $x -l ${x%.ys}.log
|
||||
done
|
||||
|
|
3
tests/liberty/unit_delay.ys
Normal file
3
tests/liberty/unit_delay.ys
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Nothing gets imported: the file lacks timing data
|
||||
read_liberty -wb -unit_delay normal.lib
|
||||
select -assert-none =*/t:$specify*
|
|
@ -84,14 +84,14 @@ assign name``_y2 = op name``_a2;
|
|||
`BIOP(xnor, ~^, 3, 3, 3)
|
||||
`BIOP(logic_and, &&, 3, 3, 1)
|
||||
`BIOP(logic_or, ||, 3, 3, 1)
|
||||
`BIOP(logic_eq, ==, 3, 3, 1)
|
||||
`BIOP(logic_ne, !=, 3, 3, 1)
|
||||
`BIOP(logic_lt, <, 3, 3, 1)
|
||||
`BIOP(logic_le, <=, 3, 3, 1)
|
||||
`BIOP(logic_gt, >, 3, 3, 1)
|
||||
`BIOP(logic_ge, >=, 3, 3, 1)
|
||||
`BIOP(eq, ==, 3, 3, 1)
|
||||
`BIOP(ne, !=, 3, 3, 1)
|
||||
`BIOP(lt, <, 3, 3, 1)
|
||||
`BIOP(le, <=, 3, 3, 1)
|
||||
`BIOP(gt, >, 3, 3, 1)
|
||||
`BIOP(ge, >=, 3, 3, 1)
|
||||
`UNOP(pos, +, 3)
|
||||
`UNOP(neg, ~, 3)
|
||||
`UNOP(not, ~, 3)
|
||||
`UNOP_REDUCE(logic_not, !, 3)
|
||||
`UNOP_REDUCE(reduce_and, &, 3)
|
||||
`UNOP_REDUCE(reduce_or, |, 3)
|
||||
|
|
224
tests/various/aiger2.ys
Normal file
224
tests/various/aiger2.ys
Normal file
|
@ -0,0 +1,224 @@
|
|||
read_verilog -icells <<EOF
|
||||
module test();
|
||||
`define CELL_AY(typ) \
|
||||
wire typ``_a, typ``_y; \
|
||||
$``typ typ(.A(typ``_a), .Y(typ``_y));
|
||||
`define CELL_ABY(typ) \
|
||||
wire typ``_a, typ``_b, typ``_y; \
|
||||
$``typ typ(.A(typ``_a), .B(typ``_b), .Y(typ``_y));
|
||||
`define CELL_SABY(typ) \
|
||||
wire typ``_a, typ``_b, typ``_y, typ``_s; \
|
||||
$``typ typ(.A(typ``_a), .B(typ``_b), .Y(typ``_y), .S(typ``_s));
|
||||
`define CELL_ABCY(typ) \
|
||||
wire typ``_a, typ``_b, typ``_c, typ``_y; \
|
||||
$``typ typ(.A(typ``_a), .B(typ``_b), .C(typ``_c), .Y(typ``_y));
|
||||
`define CELL_ABCDY(typ) \
|
||||
wire typ``_a, typ``_b, typ``_c, typ``_d, typ``_y; \
|
||||
$``typ typ(.A(typ``_a), .B(typ``_b), .C(typ``_c), .D(typ``_d), .Y(typ``_y));
|
||||
|
||||
`CELL_AY(_BUF_)
|
||||
`CELL_AY(_NOT_)
|
||||
`CELL_ABY(_AND_)
|
||||
`CELL_ABY(_NAND_)
|
||||
`CELL_ABY(_OR_)
|
||||
`CELL_ABY(_NOR_)
|
||||
`CELL_ABY(_XOR_)
|
||||
`CELL_ABY(_XNOR_)
|
||||
`CELL_ABY(_ANDNOT_)
|
||||
`CELL_ABY(_ORNOT_)
|
||||
`CELL_SABY(_MUX_)
|
||||
`CELL_SABY(_NMUX_)
|
||||
`CELL_ABCY(_AOI3_)
|
||||
`CELL_ABCY(_OAI3_)
|
||||
`CELL_ABCDY(_AOI4_)
|
||||
`CELL_ABCDY(_OAI4_)
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
expose -input c:* %ci* w:* %i
|
||||
expose c:* %co* w:* %i
|
||||
copy test gold
|
||||
select test
|
||||
write_aiger2 aiger2_gates.aig
|
||||
select -clear
|
||||
delete test
|
||||
read_aiger -module_name test aiger2_gates.aig
|
||||
select -assert-none test/t:$_AND_ test/t:$_NOT_ %% test/c:* %D
|
||||
miter -equiv -make_outcmp -flatten gold test miter
|
||||
sat -verify -show-ports -prove trigger 0 miter
|
||||
|
||||
design -reset
|
||||
read_verilog -icells <<EOF
|
||||
module test();
|
||||
|
||||
`define BIOP(name,op,w1,w2,wy) \
|
||||
wire [w1-1:0] name``_a1; \
|
||||
wire [w2-1:0] name``_b1; \
|
||||
wire [wy-1:0] name``_y1; \
|
||||
assign name``_y1 = name``_a1 op name``_b1; \
|
||||
wire signed [w1-1:0] name``_a2; \
|
||||
wire signed [w2-1:0] name``_b2; \
|
||||
wire [wy-1:0] name``_y2; \
|
||||
assign name``_y2 = name``_a2 op name``_b2;
|
||||
|
||||
`define UNOP(name,op,w1) \
|
||||
wire signed [w1-1:0] name``_a1; \
|
||||
wire signed [w1-1:0] name``_y1; \
|
||||
assign name``_y1 = op name``_a1; \
|
||||
wire [w1-1:0] name``_a2; \
|
||||
wire [w1-1:0] name``_y2; \
|
||||
assign name``_y2 = op name``_a2;
|
||||
|
||||
`define UNOP_REDUCE(name,op,w1) \
|
||||
wire signed [w1-1:0] name``_a1; \
|
||||
wire name``_y1; \
|
||||
assign name``_y1 = op name``_a1; \
|
||||
wire [w1-1:0] name``_a2; \
|
||||
wire name``_y2; \
|
||||
assign name``_y2 = op name``_a2;
|
||||
|
||||
`BIOP(and, &, 3, 4, 5)
|
||||
`BIOP(or, |, 4, 3, 2)
|
||||
`BIOP(xor, ^, 3, 3, 3)
|
||||
`BIOP(xnor, ~^, 3, 3, 3)
|
||||
`BIOP(logic_and, &&, 4, 3, 1)
|
||||
`BIOP(logic_or, ||, 3, 3, 2)
|
||||
`BIOP(eq, ==, 3, 3, 1)
|
||||
`BIOP(ne, !=, 3, 3, 1)
|
||||
`BIOP(lt, <, 3, 3, 1)
|
||||
`BIOP(le, <=, 3, 3, 1)
|
||||
`BIOP(gt, >, 3, 3, 1)
|
||||
`BIOP(ge, >=, 3, 3, 1)
|
||||
`UNOP(not, ~, 3)
|
||||
`UNOP_REDUCE(logic_not, !, 3)
|
||||
`UNOP_REDUCE(reduce_and, &, 3)
|
||||
`UNOP_REDUCE(reduce_or, |, 3)
|
||||
`UNOP_REDUCE(reduce_xor, ^, 3)
|
||||
`UNOP_REDUCE(reduce_xnor, ~^, 3)
|
||||
|
||||
wire [3:0] mux_a, mux_b, mux_s, mux_y;
|
||||
assign mux_y = mux_s ? mux_b : mux_a;
|
||||
|
||||
wire [1:0] fa_a, fa_b, fa_c, fa_x, fa_y;
|
||||
\$fa #(
|
||||
.WIDTH(2)
|
||||
) fa(.A(fa_a), .B(fa_b), .C(fa_c), .X(fa_x), .Y(fa_y));
|
||||
|
||||
wire [1:0] bwmux_a, bwmux_b, bwmux_s, bwmux_y;
|
||||
\$bwmux #(
|
||||
.WIDTH(2)
|
||||
) bwmux(.A(bwmux_a), .B(bwmux_b), .S(bwmux_s), .Y(bwmux_y));
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
expose -input c:* %ci* w:* %i
|
||||
expose c:* %co* w:* %i
|
||||
splitnets -ports
|
||||
copy test gold
|
||||
select test
|
||||
write_aiger2 aiger2_ops.aig
|
||||
select -clear
|
||||
delete test
|
||||
read_aiger -module_name test aiger2_ops.aig
|
||||
select -assert-none test/t:$_AND_ test/t:$_NOT_ %% test/c:* %D
|
||||
miter -equiv -make_outcmp -flatten gold test miter
|
||||
sat -verify -show-ports -prove trigger 0 miter
|
||||
|
||||
design -reset
|
||||
read_verilog -icells <<EOF
|
||||
module submodule1(a, y1, y2);
|
||||
input wire [2:0] a;
|
||||
output wire [2:0] y1 = a + 1;
|
||||
output wire [2:0] y2 = a + 2;
|
||||
endmodule
|
||||
|
||||
module submodule2(a, y1);
|
||||
input wire [2:0] a;
|
||||
output wire [2:0] y1 = ~a;
|
||||
endmodule
|
||||
|
||||
module test(a, y1, y2);
|
||||
input wire [2:0] a;
|
||||
output wire [2:0] y1;
|
||||
output wire [2:0] y2;
|
||||
|
||||
wire [2:0] m1;
|
||||
wire [2:0] m2;
|
||||
|
||||
submodule2 s1(.a(a), .y1(m1));
|
||||
submodule1 s2(.a(m1), .y1(y1), .y2(m2));
|
||||
submodule2 s3(.a(m2), .y1(y2));
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
expose -input c:* %ci* w:* %i
|
||||
expose c:* %co* w:* %i
|
||||
splitnets -ports
|
||||
copy test gold
|
||||
flatten gold
|
||||
techmap submodule1
|
||||
select test
|
||||
write_aiger2 -flatten aiger2_ops.aig
|
||||
select -clear
|
||||
delete test
|
||||
read_aiger -module_name test aiger2_ops.aig
|
||||
select -assert-none test/t:$_AND_ test/t:$_NOT_ %% test/c:* %D
|
||||
miter -equiv -flatten gold test miter
|
||||
sat -verify -prove trigger 0 miter
|
||||
|
||||
design -reset
|
||||
read_verilog -icells <<EOF
|
||||
module test();
|
||||
wire [1:0] pmux_a, pmux_s, pmux_y;
|
||||
wire [3:0] pmux_b;
|
||||
\$pmux #(
|
||||
.S_WIDTH(2),
|
||||
.WIDTH(2)
|
||||
) pmux(.A(pmux_a), .B(pmux_b), .S(pmux_s), .Y(pmux_y));
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
expose -input c:* %ci* w:* %i
|
||||
expose c:* %co* w:* %i
|
||||
splitnets -ports
|
||||
opt_clean
|
||||
copy test gold
|
||||
select test
|
||||
write_aiger2 aiger2_xmodel.aig
|
||||
select -clear
|
||||
delete test
|
||||
read_aiger -module_name test aiger2_xmodel.aig
|
||||
select -assert-none test/t:$_AND_ test/t:$_NOT_ %% test/c:* %D
|
||||
|
||||
equiv_make gold test equiv
|
||||
equiv_induct -undef equiv
|
||||
equiv_status -assert equiv
|
||||
|
||||
design -reset
|
||||
read_verilog -icells <<EOF
|
||||
module sm2(input wire [1:0] a, output wire [1:0] y);
|
||||
assign y = a + 1;
|
||||
endmodule
|
||||
|
||||
module sm1(input wire [2:0] a, output wire [2:0] y);
|
||||
sm2 inst(a[1:0], y[2:1]);
|
||||
assign y[0] = !a[2];
|
||||
endmodule
|
||||
|
||||
module top(input wire [4:0] a, output wire [4:0] y);
|
||||
sm1 i1(.a(a[2:0]), .y(y[2:0]));
|
||||
sm2 i2(.a(a[4:3]), .y(y[4:3]));
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
prep -top top
|
||||
# deal with arithmetic which is unsupported inside aiger2
|
||||
techmap t:$add
|
||||
|
||||
splitnets -ports top
|
||||
write_aiger2 -flatten aiger2_flatten.aig
|
||||
flatten
|
||||
rename top gold
|
||||
read_aiger -module_name gate aiger2_flatten.aig
|
||||
miter -equiv -flatten gold gate miter
|
||||
sat -verify -prove trigger 0 miter
|
9
tests/various/logger_cmd_error.sh
Executable file
9
tests/various/logger_cmd_error.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
trap 'echo "ERROR in logger_cmd_error.sh" >&2; exit 1' ERR
|
||||
|
||||
(../../yosys -v 3 -C <<EOF
|
||||
yosys -import
|
||||
hierarchy -top nonexistent
|
||||
EOF
|
||||
) 2>&1 | grep -F "ERROR: Module \`nonexistent' not found!" > /dev/null
|
Loading…
Reference in a new issue