From eceacdb9a3b2430b684edf6bbf64ebd7f131e854 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 23 Nov 2017 04:28:51 +0100 Subject: [PATCH 01/19] Remove old BTOR back-end --- backends/btor/Makefile.inc | 3 - backends/btor/README | 23 - backends/btor/btor.cc | 1111 --------------------------------- backends/btor/verilog2btor.sh | 37 -- 4 files changed, 1174 deletions(-) delete mode 100644 backends/btor/Makefile.inc delete mode 100644 backends/btor/README delete mode 100644 backends/btor/btor.cc delete mode 100755 backends/btor/verilog2btor.sh diff --git a/backends/btor/Makefile.inc b/backends/btor/Makefile.inc deleted file mode 100644 index af7ab14dc..000000000 --- a/backends/btor/Makefile.inc +++ /dev/null @@ -1,3 +0,0 @@ - -OBJS += backends/btor/btor.o - diff --git a/backends/btor/README b/backends/btor/README deleted file mode 100644 index efcf0d8f5..000000000 --- a/backends/btor/README +++ /dev/null @@ -1,23 +0,0 @@ - -This is the Yosys BTOR backend. -It is developed by Ahmed Irfan - Fondazione Bruno Kessler, Trento, Italy - -Master git repository for the BTOR backend: -https://github.com/ahmedirfan1983/yosys - - -[[CITE]] BTOR: Bit-Precise Modelling of Word-Level Problems for Model Checking -Johannes Kepler University, Linz, Austria -http://fmv.jku.at/papers/BrummayerBiereLonsing-BPR08.pdf - - -Todos: ------- - -- Add checks for unsupported stuff - - unsupported cell types - - async resets - - etc.. - -- Add support for $lut cells - diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc deleted file mode 100644 index bbe90e85f..000000000 --- a/backends/btor/btor.cc +++ /dev/null @@ -1,1111 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * Copyright (C) 2014 Ahmed Irfan - * - * 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. - * - */ - -// [[CITE]] BTOR: Bit-Precise Modelling of Word-Level Problems for Model Checking -// Johannes Kepler University, Linz, Austria -// http://fmv.jku.at/papers/BrummayerBiereLonsing-BPR08.pdf - -#include "kernel/rtlil.h" -#include "kernel/register.h" -#include "kernel/sigtools.h" -#include "kernel/celltypes.h" -#include "kernel/log.h" -#include -#include - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct BtorDumperConfig -{ - bool subckt_mode; - bool conn_mode; - bool impltf_mode; - - std::string buf_type, buf_in, buf_out; - std::string true_type, true_out, false_type, false_out; - - BtorDumperConfig() : subckt_mode(false), conn_mode(false), impltf_mode(false) { } -}; - -struct WireInfo -{ - RTLIL::IdString cell_name; - const RTLIL::SigChunk *chunk; - - WireInfo(RTLIL::IdString c, const RTLIL::SigChunk* ch) : cell_name(c), chunk(ch) { } -}; - -struct WireInfoOrder -{ - bool operator() (const WireInfo& x, const WireInfo& y) - { - return x.chunk < y.chunk; - } -}; - -struct BtorDumper -{ - std::ostream &f; - RTLIL::Module *module; - RTLIL::Design *design; - BtorDumperConfig *config; - CellTypes ct; - - SigMap sigmap; - std::map> inter_wire_map;// for mapping the intermediate wires that are output of some cell - std::map line_ref;//mapping of ids to line_num of the btor file - std::map sig_ref;//mapping of sigspec to the line_num of the btor file - int line_num;//last line number of btor file - std::string str;//temp string for writing file - std::map basic_wires;//input wires and registers - RTLIL::IdString curr_cell; //current cell being dumped - std::map cell_type_translation, s_cell_type_translation; //RTLIL to BTOR translation - std::map>> mem_next; // memory (line_number)'s set of condition and write - BtorDumper(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig *config) : - f(f), module(module), design(design), config(config), ct(design), sigmap(module) - { - line_num=0; - str.clear(); - for(auto it=module->wires_.begin(); it!=module->wires_.end(); ++it) - { - if(it->second->port_input) - { - basic_wires[it->first]=true; - } - else - { - basic_wires[it->first]=false; - } - inter_wire_map[it->first].clear(); - } - curr_cell.clear(); - //assert - cell_type_translation["$assert"] = "root"; - //unary - cell_type_translation["$not"] = "not"; - cell_type_translation["$neg"] = "neg"; - cell_type_translation["$reduce_and"] = "redand"; - cell_type_translation["$reduce_or"] = "redor"; - cell_type_translation["$reduce_xor"] = "redxor"; - cell_type_translation["$reduce_bool"] = "redor"; - //binary - cell_type_translation["$and"] = "and"; - cell_type_translation["$or"] = "or"; - cell_type_translation["$xor"] = "xor"; - cell_type_translation["$xnor"] = "xnor"; - cell_type_translation["$shr"] = "srl"; - cell_type_translation["$shl"] = "sll"; - cell_type_translation["$sshr"] = "sra"; - cell_type_translation["$sshl"] = "sll"; - cell_type_translation["$shift"] = "srl"; - cell_type_translation["$shiftx"] = "srl"; - cell_type_translation["$lt"] = "ult"; - cell_type_translation["$le"] = "ulte"; - cell_type_translation["$gt"] = "ugt"; - cell_type_translation["$ge"] = "ugte"; - cell_type_translation["$eq"] = "eq"; - cell_type_translation["$eqx"] = "eq"; - cell_type_translation["$ne"] = "ne"; - cell_type_translation["$nex"] = "ne"; - cell_type_translation["$add"] = "add"; - cell_type_translation["$sub"] = "sub"; - cell_type_translation["$mul"] = "mul"; - cell_type_translation["$mod"] = "urem"; - cell_type_translation["$div"] = "udiv"; - //mux - cell_type_translation["$mux"] = "cond"; - //reg - cell_type_translation["$dff"] = "next"; - cell_type_translation["$adff"] = "next"; - cell_type_translation["$dffsr"] = "next"; - //memories - //nothing here - //slice - cell_type_translation["$slice"] = "slice"; - //concat - cell_type_translation["$concat"] = "concat"; - - //signed cell type translation - //binary - s_cell_type_translation["$modx"] = "srem"; - s_cell_type_translation["$mody"] = "smod"; - s_cell_type_translation["$div"] = "sdiv"; - s_cell_type_translation["$lt"] = "slt"; - s_cell_type_translation["$le"] = "slte"; - s_cell_type_translation["$gt"] = "sgt"; - s_cell_type_translation["$ge"] = "sgte"; - - } - - vector cstr_buf; - - const char *cstr(const RTLIL::IdString id) - { - str = RTLIL::unescape_id(id); - for (size_t i = 0; i < str.size(); ++i) - if (str[i] == '#' || str[i] == '=') - str[i] = '?'; - cstr_buf.push_back(str); - return cstr_buf.back().c_str(); - } - - int dump_wire(RTLIL::Wire* wire) - { - if(basic_wires[wire->name]) - { - log("writing wire %s\n", cstr(wire->name)); - auto it = line_ref.find(wire->name); - if(it==std::end(line_ref)) - { - ++line_num; - line_ref[wire->name]=line_num; - str = stringf("%d var %d %s", line_num, wire->width, cstr(wire->name)); - f << stringf("%s\n", str.c_str()); - return line_num; - } - else return it->second; - } - else // case when the wire is not basic wire - { - log("case of non-basic wire - %s\n", cstr(wire->name)); - auto it = line_ref.find(wire->name); - if(it==std::end(line_ref)) - { - std::set& dep_set = inter_wire_map.at(wire->name); - int wire_line = 0; - int wire_width = 0; - for(auto dep_set_it=dep_set.begin(); dep_set_it!=dep_set.end(); ++dep_set_it) - { - RTLIL::IdString cell_id = dep_set_it->cell_name; - if(cell_id == curr_cell) - break; - log(" -- found cell %s\n", cstr(cell_id)); - RTLIL::Cell* cell = module->cells_.at(cell_id); - const RTLIL::SigSpec* cell_output = get_cell_output(cell); - int cell_line = dump_cell(cell); - - if(dep_set.size()==1 && wire->width == cell_output->size()) - { - wire_line = cell_line; - break; - } - else - { - int prev_wire_line=0; //previously dumped wire line - int start_bit=0; - for(unsigned j=0; jchunks().size(); ++j) - { - start_bit+=cell_output->chunks().at(j).width; - if(cell_output->chunks().at(j).wire->name == wire->name) - { - prev_wire_line = wire_line; - wire_line = ++line_num; - str = stringf("%d slice %d %d %d %d;1", line_num, cell_output->chunks().at(j).width, - cell_line, start_bit-1, start_bit-cell_output->chunks().at(j).width); - f << stringf("%s\n", str.c_str()); - wire_width += cell_output->chunks().at(j).width; - if(prev_wire_line!=0) - { - ++line_num; - str = stringf("%d concat %d %d %d", line_num, wire_width, wire_line, prev_wire_line); - f << stringf("%s\n", str.c_str()); - wire_line = line_num; - } - } - } - } - } - if(dep_set.size()==0) - { - log(" - checking sigmap\n"); - RTLIL::SigSpec s = RTLIL::SigSpec(wire); - wire_line = dump_sigspec(&s, s.size()); - line_ref[wire->name]=wire_line; - } - line_ref[wire->name]=wire_line; - return wire_line; - } - else - { - log(" -- already processed wire\n"); - return it->second; - } - } - log_abort(); - return -1; - } - - int dump_memory(const RTLIL::Memory* memory) - { - log("writing memory %s\n", cstr(memory->name)); - auto it = line_ref.find(memory->name); - if(it==std::end(line_ref)) - { - ++line_num; - int address_bits = ceil_log2(memory->size); - str = stringf("%d array %d %d", line_num, memory->width, address_bits); - line_ref[memory->name]=line_num; - f << stringf("%s\n", str.c_str()); - return line_num; - } - else return it->second; - } - - int dump_memory_next(const RTLIL::Memory* memory) - { - auto mem_it = line_ref.find(memory->name); - int address_bits = ceil_log2(memory->size); - if(mem_it==std::end(line_ref)) - { - log("can not write next of a memory that is not dumped yet\n"); - log_abort(); - } - else - { - auto acond_list_it = mem_next.find(mem_it->second); - if(acond_list_it!=std::end(mem_next)) - { - std::set>& cond_list = acond_list_it->second; - if(cond_list.empty()) - { - return 0; - } - auto it=cond_list.begin(); - ++line_num; - str = stringf("%d acond %d %d %d %d %d", line_num, memory->width, address_bits, it->first, it->second, mem_it->second); - f << stringf("%s\n", str.c_str()); - ++it; - for(; it!=cond_list.end(); ++it) - { - ++line_num; - str = stringf("%d acond %d %d %d %d %d", line_num, memory->width, address_bits, it->first, it->second, line_num-1); - f << stringf("%s\n", str.c_str()); - } - ++line_num; - str = stringf("%d anext %d %d %d %d", line_num, memory->width, address_bits, mem_it->second, line_num-1); - f << stringf("%s\n", str.c_str()); - return 1; - } - return 0; - } - } - - int dump_const(const RTLIL::Const* data, int width, int offset) - { - log("writing const \n"); - if((data->flags & RTLIL::CONST_FLAG_STRING) == 0) - { - if(width<0) - width = data->bits.size() - offset; - - std::string data_str = data->as_string(); - //if(offset > 0) - data_str = data_str.substr(offset, width); - - ++line_num; - str = stringf("%d const %d %s", line_num, width, data_str.c_str()); - f << stringf("%s\n", str.c_str()); - return line_num; - } - else - log("writing const error\n"); - log_abort(); - return -1; - } - - int dump_sigchunk(const RTLIL::SigChunk* chunk) - { - log("writing sigchunk\n"); - int l=-1; - if(chunk->wire == NULL) - { - RTLIL::Const data_const(chunk->data); - l=dump_const(&data_const, chunk->width, chunk->offset); - } - else - { - if (chunk->width == chunk->wire->width && chunk->offset == 0) - l = dump_wire(chunk->wire); - else - { - int wire_line_num = dump_wire(chunk->wire); - log_assert(wire_line_num>0); - ++line_num; - str = stringf("%d slice %d %d %d %d;2", line_num, chunk->width, wire_line_num, - chunk->width + chunk->offset - 1, chunk->offset); - f << stringf("%s\n", str.c_str()); - l = line_num; - } - } - return l; - } - - int dump_sigspec(const RTLIL::SigSpec* sig, int expected_width) - { - log("writing sigspec\n"); - RTLIL::SigSpec s = sigmap(*sig); - int l = -1; - auto it = sig_ref.find(s); - if(it == std::end(sig_ref)) - { - if (s.is_chunk()) - { - l = dump_sigchunk(&s.chunks().front()); - } - else - { - int l1, l2, w1, w2; - l1 = dump_sigchunk(&s.chunks().front()); - log_assert(l1>0); - w1 = s.chunks().front().width; - for (unsigned i=1; i < s.chunks().size(); ++i) - { - l2 = dump_sigchunk(&s.chunks().at(i)); - log_assert(l2>0); - w2 = s.chunks().at(i).width; - ++line_num; - str = stringf("%d concat %d %d %d", line_num, w1+w2, l2, l1); - f << stringf("%s\n", str.c_str()); - l1=line_num; - w1+=w2; - } - l = line_num; - } - sig_ref[s] = l; - } - else - { - l = it->second; - } - - if (expected_width != s.size()) - { - log(" - changing width of sigspec\n"); - //TODO: this block may not be needed anymore, due to explicit type conversion by "splice" command - if(expected_width > s.size()) - { - //TODO: case the signal is signed - ++line_num; - str = stringf ("%d zero %d", line_num, expected_width - s.size()); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf ("%d concat %d %d %d", line_num, expected_width, line_num-1, l); - f << stringf("%s\n", str.c_str()); - l = line_num; - } - else if(expected_width < s.size()) - { - ++line_num; - str = stringf ("%d slice %d %d %d %d;3", line_num, expected_width, l, expected_width-1, 0); - f << stringf("%s\n", str.c_str()); - l = line_num; - } - } - log_assert(l>0); - return l; - } - - int dump_cell(const RTLIL::Cell* cell) - { - auto it = line_ref.find(cell->name); - if(it==std::end(line_ref)) - { - curr_cell = cell->name; - //assert cell - if(cell->type == "$assert") - { - log("writing assert cell - %s\n", cstr(cell->type)); - const RTLIL::SigSpec* expr = &cell->getPort(RTLIL::IdString("\\A")); - const RTLIL::SigSpec* en = &cell->getPort(RTLIL::IdString("\\EN")); - log_assert(expr->size() == 1); - log_assert(en->size() == 1); - int expr_line = dump_sigspec(expr, 1); - int en_line = dump_sigspec(en, 1); - int one_line = ++line_num; - str = stringf("%d one 1", line_num); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at("$eq").c_str(), 1, en_line, one_line); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at("$mux").c_str(), 1, line_num-1, - expr_line, one_line); - f << stringf("%s\n", str.c_str()); - int cell_line = ++line_num; - str = stringf("%d %s %d %d", line_num, cell_type_translation.at("$assert").c_str(), 1, -1*(line_num-1)); - //multiplying the line number with -1, which means logical negation - //the reason for negative sign is that the properties in btor are given as "negation of the original property" - //bug identified by bobosoft - //http://www.reddit.com/r/yosys/comments/1w3xig/btor_backend_bug/ - f << stringf("%s\n", str.c_str()); - line_ref[cell->name]=cell_line; - } - //unary cells - else if(cell->type == "$not" || cell->type == "$neg" || cell->type == "$pos" || cell->type == "$reduce_and" || - cell->type == "$reduce_or" || cell->type == "$reduce_xor" || cell->type == "$reduce_bool") - { - log("writing unary cell - %s\n", cstr(cell->type)); - int w = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - w = w>output_width ? w:output_width; //padding of w - int l = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), w); - int cell_line = l; - if(cell->type != "$pos") - { - cell_line = ++line_num; - bool reduced = (cell->type == "$not" || cell->type == "$neg") ? false : true; - str = stringf ("%d %s %d %d", cell_line, cell_type_translation.at(cell->type.str()).c_str(), reduced?output_width:w, l); - f << stringf("%s\n", str.c_str()); - } - if(output_width < w && (cell->type == "$not" || cell->type == "$neg" || cell->type == "$pos")) - { - ++line_num; - str = stringf ("%d slice %d %d %d %d;4", line_num, output_width, cell_line, output_width-1, 0); - f << stringf("%s\n", str.c_str()); - cell_line = line_num; - } - line_ref[cell->name]=cell_line; - } - else if(cell->type == "$reduce_xnor" || cell->type == "$logic_not")//no direct translation in btor - { - log("writing unary cell - %s\n", cstr(cell->type)); - int w = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - log_assert(output_width == 1); - int l = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), w); - if(cell->type == "$logic_not" && w > 1) - { - ++line_num; - str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l); - f << stringf("%s\n", str.c_str()); - } - else if(cell->type == "$reduce_xnor") - { - ++line_num; - str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_xor").c_str(), output_width, l); - f << stringf("%s\n", str.c_str()); - } - ++line_num; - str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$not").c_str(), output_width, l); - f << stringf("%s\n", str.c_str()); - line_ref[cell->name]=line_num; - } - //binary cells - else if(cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor" || - cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" || - cell->type == "$eqx" || cell->type == "$nex" || cell->type == "$ge" || cell->type == "$gt" ) - { - log("writing binary cell - %s\n", cstr(cell->type)); - int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - log_assert(!(cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || - cell->type == "$ge" || cell->type == "$gt") || output_width == 1); - bool l1_signed = cell->parameters.at(RTLIL::IdString("\\A_SIGNED")).as_bool(); - bool l2_signed YS_ATTRIBUTE(unused) = cell->parameters.at(RTLIL::IdString("\\B_SIGNED")).as_bool(); - int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); - - log_assert(l1_signed == l2_signed); - l1_width = l1_width > output_width ? l1_width : output_width; - l1_width = l1_width > l2_width ? l1_width : l2_width; - l2_width = l2_width > l1_width ? l2_width : l1_width; - - int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); - int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); - - ++line_num; - std::string op = cell_type_translation.at(cell->type.str()); - if(cell->type == "$lt" || cell->type == "$le" || - cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || - cell->type == "$ge" || cell->type == "$gt") - { - if(l1_signed) - op = s_cell_type_translation.at(cell->type.str()); - } - - str = stringf ("%d %s %d %d %d", line_num, op.c_str(), output_width, l1, l2); - f << stringf("%s\n", str.c_str()); - - line_ref[cell->name]=line_num; - } - else if(cell->type == "$add" || cell->type == "$sub" || cell->type == "$mul" || cell->type == "$div" || - cell->type == "$mod" ) - { - //TODO: division by zero case - log("writing binary cell - %s\n", cstr(cell->type)); - int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - bool l1_signed = cell->parameters.at(RTLIL::IdString("\\A_SIGNED")).as_bool(); - bool l2_signed = cell->parameters.at(RTLIL::IdString("\\B_SIGNED")).as_bool(); - int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); - - log_assert(l1_signed == l2_signed); - l1_width = l1_width > output_width ? l1_width : output_width; - l1_width = l1_width > l2_width ? l1_width : l2_width; - l2_width = l2_width > l1_width ? l2_width : l1_width; - - int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); - int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); - - ++line_num; - std::string op = cell_type_translation.at(cell->type.str()); - if(cell->type == "$div" && l1_signed) - op = s_cell_type_translation.at(cell->type.str()); - else if(cell->type == "$mod") - { - if(l1_signed) - op = s_cell_type_translation.at("$modx"); - else if(l2_signed) - op = s_cell_type_translation.at("$mody"); - } - str = stringf ("%d %s %d %d %d", line_num, op.c_str(), l1_width, l1, l2); - f << stringf("%s\n", str.c_str()); - - if(output_width < l1_width) - { - ++line_num; - str = stringf ("%d slice %d %d %d %d;5", line_num, output_width, line_num-1, output_width-1, 0); - f << stringf("%s\n", str.c_str()); - } - line_ref[cell->name]=line_num; - } - else if(cell->type == "$shr" || cell->type == "$shl" || cell->type == "$sshr" || cell->type == "$sshl" || cell->type == "$shift" || cell->type == "$shiftx") - { - log("writing binary cell - %s\n", cstr(cell->type)); - int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - bool l1_signed = cell->parameters.at(RTLIL::IdString("\\A_SIGNED")).as_bool(); - //bool l2_signed = cell->parameters.at(RTLIL::IdString("\\B_SIGNED")).as_bool(); - int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - l1_width = 1 << ceil_log2(l1_width); - int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); - //log_assert(l2_width <= ceil_log2(l1_width)) ); - int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); - int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), ceil_log2(l1_width)); - int cell_output = ++line_num; - str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), l1_width, l1, l2); - f << stringf("%s\n", str.c_str()); - - if(l2_width > ceil_log2(l1_width)) - { - int extra_width = l2_width - ceil_log2(l1_width); - l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); - ++line_num; - str = stringf ("%d slice %d %d %d %d;6", line_num, extra_width, l2, l2_width-1, l2_width-extra_width); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf ("%d one %d", line_num, extra_width); - f << stringf("%s\n", str.c_str()); - int mux = ++line_num; - str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$gt").c_str(), 1, line_num-2, line_num-1); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf("%d %s %d", line_num, l1_signed && cell->type == "$sshr" ? "ones":"zero", l1_width); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf ("%d %s %d %d %d %d", line_num, cell_type_translation.at("$mux").c_str(), l1_width, mux, line_num-1, cell_output); - f << stringf("%s\n", str.c_str()); - cell_output = line_num; - } - - if(output_width < l1_width) - { - ++line_num; - str = stringf ("%d slice %d %d %d %d;5", line_num, output_width, cell_output, output_width-1, 0); - f << stringf("%s\n", str.c_str()); - cell_output = line_num; - } - line_ref[cell->name] = cell_output; - } - else if(cell->type == "$logic_and" || cell->type == "$logic_or")//no direct translation in btor - { - log("writing binary cell - %s\n", cstr(cell->type)); - int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - log_assert(output_width == 1); - int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); - int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width); - int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); - if(l1_width >1) - { - ++line_num; - str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l1); - f << stringf("%s\n", str.c_str()); - l1 = line_num; - } - if(l2_width > 1) - { - ++line_num; - str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l2); - f << stringf("%s\n", str.c_str()); - l2 = line_num; - } - if(cell->type == "$logic_and") - { - ++line_num; - str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$and").c_str(), output_width, l1, l2); - } - else if(cell->type == "$logic_or") - { - ++line_num; - str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$or").c_str(), output_width, l1, l2); - } - f << stringf("%s\n", str.c_str()); - line_ref[cell->name]=line_num; - } - //multiplexers - else if(cell->type == "$mux") - { - log("writing mux cell\n"); - int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); - int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); - int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width); - int s = dump_sigspec(&cell->getPort(RTLIL::IdString("\\S")), 1); - ++line_num; - str = stringf ("%d %s %d %d %d %d", - line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, s, l2, l1); - //if s is 0 then l1, if s is 1 then l2 //according to the implementation of mux cell - f << stringf("%s\n", str.c_str()); - line_ref[cell->name]=line_num; - } - else if(cell->type == "$pmux") - { - log("writing pmux cell\n"); - int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); - int select_width = cell->parameters.at(RTLIL::IdString("\\S_WIDTH")).as_int(); - int default_case = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); - int cases = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width*select_width); - int select = dump_sigspec(&cell->getPort(RTLIL::IdString("\\S")), select_width); - int *c = new int[select_width]; - - for (int i=0; i=0; --i) - { - ++line_num; - str = stringf ("%d cond %d %d %d %d", line_num, output_width, c[i], c[i]+1, line_num-1); - f << stringf("%s\n", str.c_str()); - } - - line_ref[cell->name]=line_num; - } - //registers - else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") - { - //TODO: remodelling of adff cells - log("writing cell - %s\n", cstr(cell->type)); - int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); - log(" - width is %d\n", output_width); - int cond = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLK")), 1); - bool polarity = cell->parameters.at(RTLIL::IdString("\\CLK_POLARITY")).as_bool(); - const RTLIL::SigSpec* cell_output = &cell->getPort(RTLIL::IdString("\\Q")); - int value = dump_sigspec(&cell->getPort(RTLIL::IdString("\\D")), output_width); - unsigned start_bit = 0; - for(unsigned i=0; ichunks().size(); ++i) - { - output_width = cell_output->chunks().at(i).width; - log_assert( output_width == cell_output->chunks().at(i).wire->width);//full reg is given the next value - int reg = dump_wire(cell_output->chunks().at(i).wire);//register - int slice = value; - if(cell_output->chunks().size()>1) - { - start_bit+=output_width; - slice = ++line_num; - str = stringf ("%d slice %d %d %d %d;", line_num, output_width, value, start_bit-1, - start_bit-output_width); - f << stringf("%s\n", str.c_str()); - } - if(cell->type == "$dffsr") - { - int sync_reset = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLR")), 1); - bool sync_reset_pol = cell->parameters.at(RTLIL::IdString("\\CLR_POLARITY")).as_bool(); - int sync_reset_value = dump_sigspec(&cell->getPort(RTLIL::IdString("\\SET")), - output_width); - bool sync_reset_value_pol = cell->parameters.at(RTLIL::IdString("\\SET_POLARITY")).as_bool(); - ++line_num; - str = stringf ("%d %s %d %s%d %s%d %d", line_num, cell_type_translation.at("$mux").c_str(), - output_width, sync_reset_pol ? "":"-", sync_reset, sync_reset_value_pol? "":"-", - sync_reset_value, slice); - f << stringf("%s\n", str.c_str()); - slice = line_num; - } - ++line_num; - str = stringf ("%d %s %d %s%d %d %d", line_num, cell_type_translation.at("$mux").c_str(), - output_width, polarity?"":"-", cond, slice, reg); - - f << stringf("%s\n", str.c_str()); - int next = line_num; - if(cell->type == "$adff") - { - int async_reset = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ARST")), 1); - bool async_reset_pol = cell->parameters.at(RTLIL::IdString("\\ARST_POLARITY")).as_bool(); - int async_reset_value = dump_const(&cell->parameters.at(RTLIL::IdString("\\ARST_VALUE")), - output_width, 0); - ++line_num; - str = stringf ("%d %s %d %s%d %d %d", line_num, cell_type_translation.at("$mux").c_str(), - output_width, async_reset_pol ? "":"-", async_reset, async_reset_value, next); - f << stringf("%s\n", str.c_str()); - } - ++line_num; - str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), - output_width, reg, next); - f << stringf("%s\n", str.c_str()); - } - line_ref[cell->name]=line_num; - } - //memories - else if(cell->type == "$memrd") - { - log("writing memrd cell\n"); - if (cell->parameters.at("\\CLK_ENABLE").as_bool() == true) - log_error("The btor backen does not support $memrd cells with built-in registers. Run memory_dff with -wr_only.\n"); - str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string(); - int mem = dump_memory(module->memories.at(RTLIL::IdString(str.c_str()))); - int address_width = cell->parameters.at(RTLIL::IdString("\\ABITS")).as_int(); - int address = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ADDR")), address_width); - int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); - ++line_num; - str = stringf("%d read %d %d %d", line_num, data_width, mem, address); - f << stringf("%s\n", str.c_str()); - line_ref[cell->name]=line_num; - } - else if(cell->type == "$memwr") - { - log("writing memwr cell\n"); - if (cell->parameters.at("\\CLK_ENABLE").as_bool() == false) - log_error("The btor backen does not support $memwr cells without built-in registers. Run memory_dff (but with -wr_only).\n"); - int clk = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLK")), 1); - bool polarity = cell->parameters.at(RTLIL::IdString("\\CLK_POLARITY")).as_bool(); - int enable = dump_sigspec(&cell->getPort(RTLIL::IdString("\\EN")), 1); - int address_width = cell->parameters.at(RTLIL::IdString("\\ABITS")).as_int(); - int address = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ADDR")), address_width); - int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); - int data = dump_sigspec(&cell->getPort(RTLIL::IdString("\\DATA")), data_width); - str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string(); - int mem = dump_memory(module->memories.at(RTLIL::IdString(str.c_str()))); - //check if the memory has already next - /* - auto it = mem_next.find(mem); - if(it != std::end(mem_next)) - { - ++line_num; - str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string(); - RTLIL::Memory *memory = module->memories.at(RTLIL::IdString(str.c_str())); - int address_bits = ceil_log2(memory->size); - str = stringf("%d array %d %d", line_num, memory->width, address_bits); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf("%d eq 1 %d %d; mem invar", line_num, mem, line_num - 1); - f << stringf("%s\n", str.c_str()); - mem = line_num - 1; - } - */ - ++line_num; - if(polarity) - str = stringf("%d one 1", line_num); - else - str = stringf("%d zero 1", line_num); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf("%d eq 1 %d %d", line_num, clk, line_num-1); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf("%d and 1 %d %d", line_num, line_num-1, enable); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf("%d write %d %d %d %d %d", line_num, data_width, address_width, mem, address, data); - f << stringf("%s\n", str.c_str()); - /* - ++line_num; - str = stringf("%d acond %d %d %d %d %d", line_num, data_width, address_width, line_num-2, line_num-1, mem); - f << stringf("%s\n", str.c_str()); - ++line_num; - str = stringf("%d anext %d %d %d %d", line_num, data_width, address_width, mem, line_num-1); - f << stringf("%s\n", str.c_str()); - */ - mem_next[mem].insert(std::make_pair(line_num-1, line_num)); - } - else if(cell->type == "$slice") - { - log("writing slice cell\n"); - const RTLIL::SigSpec* input = &cell->getPort(RTLIL::IdString("\\A")); - int input_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - log_assert(input->size() == input_width); - int input_line = dump_sigspec(input, input_width); - const RTLIL::SigSpec* output YS_ATTRIBUTE(unused) = &cell->getPort(RTLIL::IdString("\\Y")); - int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - log_assert(output->size() == output_width); - int offset = cell->parameters.at(RTLIL::IdString("\\OFFSET")).as_int(); - ++line_num; - str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, input_line, output_width+offset-1, offset); - f << stringf("%s\n", str.c_str()); - line_ref[cell->name]=line_num; - } - else if(cell->type == "$concat") - { - log("writing concat cell\n"); - const RTLIL::SigSpec* input_a = &cell->getPort(RTLIL::IdString("\\A")); - int input_a_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - log_assert(input_a->size() == input_a_width); - int input_a_line = dump_sigspec(input_a, input_a_width); - const RTLIL::SigSpec* input_b = &cell->getPort(RTLIL::IdString("\\B")); - int input_b_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); - log_assert(input_b->size() == input_b_width); - int input_b_line = dump_sigspec(input_b, input_b_width); - ++line_num; - str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), input_a_width+input_b_width, - input_a_line, input_b_line); - f << stringf("%s\n", str.c_str()); - line_ref[cell->name]=line_num; - } - curr_cell.clear(); - return line_num; - } - else - { - return it->second; - } - } - - const RTLIL::SigSpec* get_cell_output(RTLIL::Cell* cell) - { - const RTLIL::SigSpec *output_sig = nullptr; - if (cell->type == "$memrd") - { - output_sig = &cell->getPort(RTLIL::IdString("\\DATA")); - } - else if(cell->type == "$memwr" || cell->type == "$assert") - { - //no output - } - else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") - { - output_sig = &cell->getPort(RTLIL::IdString("\\Q")); - } - else - { - output_sig = &cell->getPort(RTLIL::IdString("\\Y")); - } - return output_sig; - } - - void dump_property(RTLIL::Wire *wire) - { - int l = dump_wire(wire); - ++line_num; - str = stringf("%d root 1 %d", line_num, l); - f << stringf("%s\n", str.c_str()); - } - - void dump() - { - f << stringf(";module %s\n", cstr(module->name)); - - log("creating intermediate wires map\n"); - //creating map of intermediate wires as output of some cell - for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) - { - RTLIL::Cell *cell = it->second; - const RTLIL::SigSpec* output_sig = get_cell_output(cell); - if(output_sig==nullptr) - continue; - RTLIL::SigSpec s = sigmap(*output_sig); - output_sig = &s; - log(" - %s\n", cstr(it->second->type)); - if (cell->type == "$memrd") - { - for(unsigned i=0; ichunks().size(); ++i) - { - RTLIL::Wire *w = output_sig->chunks().at(i).wire; - RTLIL::IdString wire_id = w->name; - inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); - } - } - else if(cell->type == "$memwr") - { - continue;//nothing to do - } - else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") - { - RTLIL::IdString wire_id = output_sig->chunks().front().wire->name; - for(unsigned i=0; ichunks().size(); ++i) - { - RTLIL::Wire *w = output_sig->chunks().at(i).wire; - RTLIL::IdString wire_id = w->name; - inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); - basic_wires[wire_id] = true; - } - } - else - { - for(unsigned i=0; ichunks().size(); ++i) - { - RTLIL::Wire *w = output_sig->chunks().at(i).wire; - RTLIL::IdString wire_id = w->name; - inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); - } - } - } - - log("writing input\n"); - std::map inputs, outputs; - std::vector safety; - - for (auto &wire_it : module->wires_) { - RTLIL::Wire *wire = wire_it.second; - if (wire->port_input) - inputs[wire->port_id] = wire; - if (wire->port_output) { - outputs[wire->port_id] = wire; - if (wire->name.str().find("safety") != std::string::npos ) - safety.push_back(wire); - } - } - - f << stringf(";inputs\n"); - for (auto &it : inputs) { - RTLIL::Wire *wire = it.second; - dump_wire(wire); - } - f << stringf("\n"); - - log("writing memories\n"); - for(auto mem_it = module->memories.begin(); mem_it != module->memories.end(); ++mem_it) - { - dump_memory(mem_it->second); - } - - log("writing output wires\n"); - for (auto &it : outputs) { - RTLIL::Wire *wire = it.second; - dump_wire(wire); - } - - log("writing cells\n"); - for(auto cell_it = module->cells_.begin(); cell_it != module->cells_.end(); ++cell_it) - { - dump_cell(cell_it->second); - } - - log("writing memory next"); - for(auto mem_it = module->memories.begin(); mem_it != module->memories.end(); ++mem_it) - { - dump_memory_next(mem_it->second); - } - - for(auto it: safety) - dump_property(it); - - f << stringf("\n"); - - log("writing outputs info\n"); - f << stringf(";outputs\n"); - for (auto &it : outputs) { - RTLIL::Wire *wire = it.second; - int l = dump_wire(wire); - f << stringf(";%d %s", l, cstr(wire->name)); - } - f << stringf("\n"); - } - - static void dump(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig &config) - { - BtorDumper dumper(f, module, design, &config); - dumper.dump(); - } -}; - -struct BtorBackend : public Backend { - BtorBackend() : Backend("btor", "write design to BTOR file") { } - - virtual void help() - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" write_btor [filename]\n"); - log("\n"); - log("Write the current design to an BTOR file.\n"); - } - - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) - { - std::string top_module_name; - std::string buf_type, buf_in, buf_out; - std::string true_type, true_out; - std::string false_type, false_out; - BtorDumperConfig config; - - log_header(design, "Executing BTOR backend.\n"); - - size_t argidx=1; - extra_args(f, filename, args, argidx); - - if (top_module_name.empty()) - for (auto & mod_it:design->modules_) - if (mod_it.second->get_bool_attribute("\\top")) - top_module_name = mod_it.first.str(); - - *f << stringf("; Generated by %s\n", yosys_version_str); - *f << stringf("; %s developed and maintained by Clifford Wolf \n", yosys_version_str); - *f << stringf("; BTOR Backend developed by Ahmed Irfan - Fondazione Bruno Kessler, Trento, Italy\n"); - *f << stringf(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); - - std::vector mod_list; - - for (auto module_it : design->modules_) - { - RTLIL::Module *module = module_it.second; - if (module->get_bool_attribute("\\blackbox")) - continue; - - if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in BTOR backend!\n", RTLIL::id2cstr(module->name)); - - if (module->name == RTLIL::escape_id(top_module_name)) { - BtorDumper::dump(*f, module, design, config); - top_module_name.clear(); - continue; - } - - mod_list.push_back(module); - } - - if (!top_module_name.empty()) - log_error("Can't find top module `%s'!\n", top_module_name.c_str()); - - for (auto module : mod_list) - BtorDumper::dump(*f, module, design, config); - } -} BtorBackend; - -PRIVATE_NAMESPACE_END diff --git a/backends/btor/verilog2btor.sh b/backends/btor/verilog2btor.sh deleted file mode 100755 index dfd7f1a85..000000000 --- a/backends/btor/verilog2btor.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# -# Script to write BTOR from Verilog design -# - -if [ "$#" -ne 3 ]; then - echo "Usage: $0 input.v output.btor top-module-name" >&2 - exit 1 -fi -if ! [ -e "$1" ]; then - echo "$1 not found" >&2 - exit 1 -fi - -FULL_PATH=$(readlink -f $1) -DIR=$(dirname $FULL_PATH) - -./yosys -q -p " -read_verilog -sv $1; -hierarchy -top $3; -hierarchy -libdir $DIR; -hierarchy -check; -proc; -opt; opt_expr -mux_undef; opt; -rename -hide;;; -#techmap -map +/pmux2mux.v;; -splice; opt; -memory_dff -wr_only; -memory_collect;; -flatten;; -memory_unpack; -splitnets -driver; -setundef -zero -undriven; -opt;;; -write_btor $2;" - From 6ee305553ae2b8f77896b19bfb7ea16229960ee7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 23 Nov 2017 06:38:57 +0100 Subject: [PATCH 02/19] Add skeleton for new BTOR back-end --- backends/btor/Makefile.inc | 3 + backends/btor/btor.cc | 213 +++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 backends/btor/Makefile.inc create mode 100644 backends/btor/btor.cc diff --git a/backends/btor/Makefile.inc b/backends/btor/Makefile.inc new file mode 100644 index 000000000..af7ab14dc --- /dev/null +++ b/backends/btor/Makefile.inc @@ -0,0 +1,3 @@ + +OBJS += backends/btor/btor.o + diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc new file mode 100644 index 000000000..ca106d387 --- /dev/null +++ b/backends/btor/btor.cc @@ -0,0 +1,213 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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/rtlil.h" +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/log.h" +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct BtorWorker +{ + std::ostream &f; + SigMap sigmap; + RTLIL::Module *module; + bool verbose; + int next_nid; + + // => + dict sorts_bv; + + // (, ) => + dict, int> sorts_mem; + + // SigBit => (, ) + dict> bit_nid; + + // => + dict nid_width; + + // SigSpec => + dict sig_nid; + + // bit to driving cell + dict bit_cell; + + int get_bv_sid(int width) + { + if (sorts_bv.count(width) == 0) { + int nid = next_nid++; + f << stringf("%d sort bitvec %d\n", nid, width); + sorts_bv[width] = nid; + } + return sorts_bv.at(width); + } + + int get_sig_nid(SigSpec sig) + { + sigmap.apply(sig); + + if (sig_nid.count(sig) == 0) + { + // , + vector> nidbits; + + // collect all bits + for (int i = 0; i < GetSize(sig); i++) + { + SigBit bit = sig[i]; + + if (bit_nid.count(bit) == 0) + { + // FIXME + log_abort(); + } + + nidbits.push_back(bit_nid.at(bit)); + } + + int width = 0; + int nid = -1; + + // group bits and emit slice-concat chain + for (int i = 0; i < GetSize(nidbits); i++) + { + int nid2 = nidbits[i].first; + int lower = nidbits[i].second; + int upper = lower; + + while (i+1 < GetSize(nidbits) && nidbits[i+1].first == nidbits[i].first && + nidbits[i+1].second == nidbits[i].second+1) + upper++, i++; + + int nid3 = nid2; + + if (lower != 0 && upper+1 != nid_width.at(nid2)) { + int sid = get_bv_sid(upper-lower+1); + nid3 = next_nid++; + f << stringf("%d slice %d %d %d %d\n", nid3, sid, nid, upper, lower); + } + + int nid4 = nid3; + + if (nid >= 0) { + int sid = get_bv_sid(width+upper-lower+1); + int nid4 = next_nid++; + f << stringf("%d concat %d %d %d\n", nid4, sid, nid, nid3); + } + + width += upper-lower+1; + nid = nid4; + } + + sig_nid[sig] = nid; + nid_width[nid] = width; + } + + return sig_nid.at(sig); + } + + BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose) : + f(f), sigmap(module), module(module), verbose(verbose), next_nid(1) + { + for (auto wire : module->wires()) + { + if (!wire->port_id || !wire->port_input) + continue; + + SigSpec sig = sigmap(wire); + int sid = get_bv_sid(GetSize(sig)); + int nid = next_nid++; + + f << stringf("%d input %d %s\n", nid, sid, log_id(wire)); + + for (int i = 0; i < GetSize(sig); i++) + bit_nid[sig[i]] = make_pair(nid, i); + sig_nid[sig] = nid; + nid_width[nid] = GetSize(sig); + } + + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) + { + if (!cell->output(conn.first)) + continue; + + for (auto bit : sigmap(conn.second)) + bit_cell[bit] = cell; + } + + for (auto wire : module->wires()) + { + if (!wire->port_id || !wire->port_output) + continue; + + int nid = get_sig_nid(wire); + f << stringf("%d output %d %s\n", next_nid++, nid, log_id(wire)); + } + } +}; + +struct BtorBackend : public Backend { + BtorBackend() : Backend("btor", "write design to BTOR file") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" write_btor [options] [filename]\n"); + log("\n"); + log("Write a BTOR description of the current design.\n"); + log("\n"); + } + virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + { + bool verbose = false; + + log_header(design, "Executing BTOR backend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-verbose") { + verbose = true; + continue; + } + break; + } + extra_args(f, filename, args, argidx); + + RTLIL::Module *topmod = design->top_module(); + + if (topmod == nullptr) + log_cmd_error("No top module found.\n"); + + *f << stringf("; BTOR description generated by %s for module %s.\n", + yosys_version_str, log_id(topmod)); + + BtorWorker(*f, topmod, verbose); + + *f << stringf("; end of yosys output\n"); + } +} BtorBackend; + +PRIVATE_NAMESPACE_END From e41dcaa7594e501d24852ca29e3c699d85c394bf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 23 Nov 2017 08:28:29 +0100 Subject: [PATCH 03/19] Progress with new BTOR backend --- backends/btor/btor.cc | 117 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 109 insertions(+), 8 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index ca106d387..77ae34797 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -53,6 +53,11 @@ struct BtorWorker // bit to driving cell dict bit_cell; + // nids for constants + dict consts; + + pool cell_recursion_guard; + int get_bv_sid(int width) { if (sorts_bv.count(width) == 0) { @@ -63,7 +68,57 @@ struct BtorWorker return sorts_bv.at(width); } - int get_sig_nid(SigSpec sig) + void export_cell(Cell *cell) + { + log_assert(cell_recursion_guard.count(cell) == 0); + cell_recursion_guard.insert(cell); + + if (cell->type.in("$add", "$sub")) + { + string btor_op; + if (cell->type == "$add") btor_op = "add"; + if (cell->type == "$sub") btor_op = "sub"; + log_assert(!btor_op.empty()); + + int width = GetSize(cell->getPort("\\Y")); + width = std::max(width, GetSize(cell->getPort("\\A"))); + width = std::max(width, GetSize(cell->getPort("\\B"))); + + bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; + bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; + + int sid = get_bv_sid(width); + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); + + int nid = next_nid++; + f << stringf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); + + SigSpec sig = sigmap(cell->getPort("\\Y")); + + if (GetSize(sig) < width) { + int sid = get_bv_sid(GetSize(sig)); + int nid2 = next_nid++; + f << stringf("%d slice %d %d %d 0\n", nid2, sid, nid, GetSize(sig)-1); + nid = nid2; + } + + for (int i = 0; i < GetSize(sig); i++) + bit_nid[sig[i]] = make_pair(nid, i); + + sig_nid[sig] = nid; + nid_width[nid] = GetSize(sig); + + goto okay; + } + + log_error("Unsupported cell type: %s\n", log_id(cell)); + + okay: + cell_recursion_guard.erase(cell); + } + + int get_sig_nid(SigSpec sig, int to_width = -1, bool is_signed = false) { sigmap.apply(sig); @@ -79,8 +134,33 @@ struct BtorWorker if (bit_nid.count(bit) == 0) { - // FIXME - log_abort(); + if (bit.wire == nullptr) + { + Const c(bit.data); + + while (i+GetSize(c) < GetSize(sig) && sig[i+GetSize(c)].wire == nullptr) + c.bits.push_back(sig[i+GetSize(c)].data); + + if (consts.count(c) == 0) { + int sid = get_bv_sid(GetSize(c)); + int nid = next_nid++; + f << stringf("%d const %d %s\n", nid, sid, c.as_string().c_str()); + consts[c] = nid; + } + + int nid = consts.at(c); + + for (int j = 0; j < GetSize(c); j++) + nidbits.push_back(make_pair(nid, j)); + + i += GetSize(c)-1; + continue; + } + else + { + export_cell(bit_cell.at(bit)); + log_assert(bit_nid.count(bit)); + } } nidbits.push_back(bit_nid.at(bit)); @@ -124,7 +204,28 @@ struct BtorWorker nid_width[nid] = width; } - return sig_nid.at(sig); + int nid = sig_nid.at(sig); + + if (to_width >= 0 && to_width != GetSize(sig)) + { + if (to_width < GetSize(sig)) + { + int sid = get_bv_sid(to_width); + int nid2 = next_nid++; + f << stringf("%d slice %d %d %d 0\n", nid2, sid, nid, to_width-1); + nid = nid2; + } + else + { + int sid = get_bv_sid(to_width); + int nid2 = next_nid++; + f << stringf("%d %s %d %d %d\n", nid2, is_signed ? "sext" : "uext", + sid, nid, to_width - GetSize(sig)); + nid = nid2; + } + } + + return nid; } BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose) : @@ -188,10 +289,10 @@ struct BtorBackend : public Backend { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-verbose") { - verbose = true; - continue; - } + // if (args[argidx] == "-verbose") { + // verbose = true; + // continue; + // } break; } extra_args(f, filename, args, argidx); From cc2495d48d1b5d89b095174f55af0b6e848bdd10 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 23 Nov 2017 18:14:53 +0100 Subject: [PATCH 04/19] Progress in new BTOR back-end --- backends/btor/btor.cc | 90 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 16 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 77ae34797..156c7cd47 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -56,6 +56,9 @@ struct BtorWorker // nids for constants dict consts; + // ff inputs that need to be evaluated (, ) + vector> ff_todo; + pool cell_recursion_guard; int get_bv_sid(int width) @@ -68,16 +71,26 @@ struct BtorWorker return sorts_bv.at(width); } + void add_nid_sig(int nid, const SigSpec &sig) + { + for (int i = 0; i < GetSize(sig); i++) + bit_nid[sig[i]] = make_pair(nid, i); + + sig_nid[sig] = nid; + nid_width[nid] = GetSize(sig); + } + void export_cell(Cell *cell) { log_assert(cell_recursion_guard.count(cell) == 0); cell_recursion_guard.insert(cell); - if (cell->type.in("$add", "$sub")) + if (cell->type.in("$add", "$sub", "$xor")) { string btor_op; if (cell->type == "$add") btor_op = "add"; if (cell->type == "$sub") btor_op = "sub"; + if (cell->type == "$xor") btor_op = "xor"; log_assert(!btor_op.empty()); int width = GetSize(cell->getPort("\\Y")); @@ -92,27 +105,62 @@ struct BtorWorker int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); int nid = next_nid++; - f << stringf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); + f << stringf("%d %s %d %d %d ; %s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, log_id(cell)); SigSpec sig = sigmap(cell->getPort("\\Y")); if (GetSize(sig) < width) { int sid = get_bv_sid(GetSize(sig)); int nid2 = next_nid++; - f << stringf("%d slice %d %d %d 0\n", nid2, sid, nid, GetSize(sig)-1); + f << stringf("%d slice %d %d %d 0 ; %s\n", nid2, sid, nid, GetSize(sig)-1, log_id(cell)); nid = nid2; } - for (int i = 0; i < GetSize(sig); i++) - bit_nid[sig[i]] = make_pair(nid, i); - - sig_nid[sig] = nid; - nid_width[nid] = GetSize(sig); - + add_nid_sig(nid, sig); goto okay; } - log_error("Unsupported cell type: %s\n", log_id(cell)); + if (cell->type.in("$mux", "$_MUX_")) + { + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); + SigSpec sig_s = sigmap(cell->getPort("\\S")); + SigSpec sig_y = sigmap(cell->getPort("\\Y")); + + int nid_a = get_sig_nid(sig_a); + int nid_b = get_sig_nid(sig_b); + int nid_s = get_sig_nid(sig_s); + + int sid = get_bv_sid(GetSize(sig_y)); + int nid = next_nid++; + f << stringf("%d ite %d %d %d %d ; %s\n", nid, sid, nid_s, nid_b, nid_a, log_id(cell)); + + add_nid_sig(nid, sig_y); + goto okay; + } + + if (cell->type.in("$dff", "$ff", "$_DFF_P_", "$_DFF_N", "$_FF_")) + { + SigSpec sig_d = sigmap(cell->getPort("\\D")); + SigSpec sig_q = sigmap(cell->getPort("\\Q")); + + string symbol = log_signal(sig_q); + if (symbol.find(' ') != string::npos) + symbol = log_id(cell); + + if (symbol[0] == '\\') + symbol = symbol.substr(1); + + int sid = get_bv_sid(GetSize(sig_q)); + int nid = next_nid++; + f << stringf("%d state %d %s ; %s\n", nid, sid, symbol.c_str(), log_id(cell)); + + ff_todo.push_back(make_pair(nid, sig_d)); + add_nid_sig(nid, sig_q); + goto okay; + } + + log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); okay: cell_recursion_guard.erase(cell); @@ -146,6 +194,7 @@ struct BtorWorker int nid = next_nid++; f << stringf("%d const %d %s\n", nid, sid, c.as_string().c_str()); consts[c] = nid; + nid_width[nid] = GetSize(c); } int nid = consts.at(c); @@ -182,7 +231,7 @@ struct BtorWorker int nid3 = nid2; - if (lower != 0 && upper+1 != nid_width.at(nid2)) { + if (lower != 0 || upper+1 != nid_width.at(nid2)) { int sid = get_bv_sid(upper-lower+1); nid3 = next_nid++; f << stringf("%d slice %d %d %d %d\n", nid3, sid, nid, upper, lower); @@ -241,11 +290,7 @@ struct BtorWorker int nid = next_nid++; f << stringf("%d input %d %s\n", nid, sid, log_id(wire)); - - for (int i = 0; i < GetSize(sig); i++) - bit_nid[sig[i]] = make_pair(nid, i); - sig_nid[sig] = nid; - nid_width[nid] = GetSize(sig); + add_nid_sig(nid, sig); } for (auto cell : module->cells()) @@ -266,6 +311,19 @@ struct BtorWorker int nid = get_sig_nid(wire); f << stringf("%d output %d %s\n", next_nid++, nid, log_id(wire)); } + + while (!ff_todo.empty()) + { + vector> todo; + todo.swap(ff_todo); + + for (auto &it : todo) + { + int nid = get_sig_nid(it.second); + int sid = get_bv_sid(GetSize(it.second)); + f << stringf("%d next %d %d %d\n", next_nid++, sid, it.first, nid); + } + } } }; From b3d6b277ea63fc9da4a728f5e0a34a2e38ebdf5f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 23 Nov 2017 18:50:10 +0100 Subject: [PATCH 05/19] Progress in new BTOR back-end --- backends/btor/btor.cc | 98 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 3 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 156c7cd47..61caf57e4 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -33,7 +33,9 @@ struct BtorWorker SigMap sigmap; RTLIL::Module *module; bool verbose; - int next_nid; + + int next_nid = 1; + int initstate_nid = -1; // => dict sorts_bv; @@ -120,6 +122,46 @@ struct BtorWorker goto okay; } + if (cell->type.in("$logic_and", "$logic_or")) + { + string btor_op; + if (cell->type == "$logic_and") btor_op = "and"; + if (cell->type == "$logic_or") btor_op = "or"; + log_assert(!btor_op.empty()); + + int sid = get_bv_sid(1); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_b = get_sig_nid(cell->getPort("\\B")); + + if (GetSize(cell->getPort("\\A")) > 1) { + int nid_red_a = next_nid++; + f << stringf("%d redor %d %d\n", nid_red_a, sid, nid_a); + nid_a = nid_red_a; + } + + if (GetSize(cell->getPort("\\B")) > 1) { + int nid_red_b = next_nid++; + f << stringf("%d redor %d %d\n", nid_red_b, sid, nid_b); + nid_b = nid_red_b; + } + + int nid = next_nid++; + f << stringf("%d %s %d %d %d ; %s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, log_id(cell)); + + SigSpec sig = sigmap(cell->getPort("\\Y")); + + if (GetSize(sig) > 1) { + int sid = get_bv_sid(GetSize(sig)); + int zeros_nid = get_sig_nid(Const(0, GetSize(sig)-1)); + int nid2 = next_nid++; + f << stringf("%d concat %d %d %d ; %s\n", nid2, sid, zeros_nid, nid, log_id(cell)); + nid = nid2; + } + + add_nid_sig(nid, sig); + goto okay; + } + if (cell->type.in("$mux", "$_MUX_")) { SigSpec sig_a = sigmap(cell->getPort("\\A")); @@ -160,6 +202,25 @@ struct BtorWorker goto okay; } + if (cell->type == "$initstate") + { + SigSpec sig_y = sigmap(cell->getPort("\\Y")); + + if (initstate_nid < 0) + { + int sid = get_bv_sid(1); + int one_nid = get_sig_nid(Const(1, 1)); + int zero_nid = get_sig_nid(Const(0, 1)); + initstate_nid = next_nid++; + f << stringf("%d state %d ; initstate\n", initstate_nid, sid); + f << stringf("%d init %d %d %d ; initstate\n", next_nid++, sid, initstate_nid, one_nid); + f << stringf("%d next %d %d %d ; initstate\n", next_nid++, sid, initstate_nid, zero_nid); + } + + add_nid_sig(initstate_nid, sig_y); + goto okay; + } + log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); okay: @@ -234,7 +295,7 @@ struct BtorWorker if (lower != 0 || upper+1 != nid_width.at(nid2)) { int sid = get_bv_sid(upper-lower+1); nid3 = next_nid++; - f << stringf("%d slice %d %d %d %d\n", nid3, sid, nid, upper, lower); + f << stringf("%d slice %d %d %d %d\n", nid3, sid, nid2, upper, lower); } int nid4 = nid3; @@ -278,7 +339,7 @@ struct BtorWorker } BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose) : - f(f), sigmap(module), module(module), verbose(verbose), next_nid(1) + f(f), sigmap(module), module(module), verbose(verbose) { for (auto wire : module->wires()) { @@ -312,6 +373,37 @@ struct BtorWorker f << stringf("%d output %d %s\n", next_nid++, nid, log_id(wire)); } + for (auto cell : module->cells()) + { + if (cell->type == "$assume") + { + int sid = get_bv_sid(1); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_en = get_sig_nid(cell->getPort("\\EN")); + int nid_not_en = next_nid++; + int nid_a_or_not_en = next_nid++; + int nid = next_nid++; + + f << stringf("%d not %d %d\n", nid_not_en, sid, nid_en); + f << stringf("%d or %d %d %d\n", nid_a_or_not_en, sid, nid_a, nid_not_en); + f << stringf("%d constraint %d ; %s\n", nid, nid_a_or_not_en, log_id(cell)); + } + + if (cell->type == "$assert") + { + int sid = get_bv_sid(1); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_en = get_sig_nid(cell->getPort("\\EN")); + int nid_not_a = next_nid++; + int nid_en_and_not_a = next_nid++; + int nid = next_nid++; + + f << stringf("%d not %d %d\n", nid_not_a, sid, nid_a); + f << stringf("%d and %d %d %d\n", nid_en_and_not_a, sid, nid_en, nid_not_a); + f << stringf("%d bad %d ; %s\n", nid, nid_en_and_not_a, log_id(cell)); + } + } + while (!ff_todo.empty()) { vector> todo; From 60d11295061956c56af5517272d0b58035c30ee6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 23 Nov 2017 23:44:39 +0100 Subject: [PATCH 06/19] Progress in new BTOR back-end --- backends/btor/btor.cc | 133 ++++++++++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 36 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 61caf57e4..2a98d1aba 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -58,16 +58,42 @@ struct BtorWorker // nids for constants dict consts; - // ff inputs that need to be evaluated (, ) - vector> ff_todo; + // ff inputs that need to be evaluated (, ) + vector> ff_todo; pool cell_recursion_guard; + pool output_symbols; + string indent; + + void btorf(const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + f << indent << vstringf(fmt, ap); + va_end(ap); + } + + void btorf_push(const string &id) + { + if (verbose) { + f << indent << stringf(" ; begin %s\n", id.c_str()); + indent += " "; + } + } + + void btorf_pop(const string &id) + { + if (verbose) { + indent = indent.substr(4); + f << indent << stringf(" ; end %s\n", id.c_str()); + } + } int get_bv_sid(int width) { if (sorts_bv.count(width) == 0) { int nid = next_nid++; - f << stringf("%d sort bitvec %d\n", nid, width); + btorf("%d sort bitvec %d\n", nid, width); sorts_bv[width] = nid; } return sorts_bv.at(width); @@ -86,6 +112,7 @@ struct BtorWorker { log_assert(cell_recursion_guard.count(cell) == 0); cell_recursion_guard.insert(cell); + btorf_push(log_id(cell)); if (cell->type.in("$add", "$sub", "$xor")) { @@ -107,14 +134,14 @@ struct BtorWorker int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); int nid = next_nid++; - f << stringf("%d %s %d %d %d ; %s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, log_id(cell)); + btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); SigSpec sig = sigmap(cell->getPort("\\Y")); if (GetSize(sig) < width) { int sid = get_bv_sid(GetSize(sig)); int nid2 = next_nid++; - f << stringf("%d slice %d %d %d 0 ; %s\n", nid2, sid, nid, GetSize(sig)-1, log_id(cell)); + btorf("%d slice %d %d %d 0\n", nid2, sid, nid, GetSize(sig)-1); nid = nid2; } @@ -135,18 +162,18 @@ struct BtorWorker if (GetSize(cell->getPort("\\A")) > 1) { int nid_red_a = next_nid++; - f << stringf("%d redor %d %d\n", nid_red_a, sid, nid_a); + btorf("%d redor %d %d\n", nid_red_a, sid, nid_a); nid_a = nid_red_a; } if (GetSize(cell->getPort("\\B")) > 1) { int nid_red_b = next_nid++; - f << stringf("%d redor %d %d\n", nid_red_b, sid, nid_b); + btorf("%d redor %d %d\n", nid_red_b, sid, nid_b); nid_b = nid_red_b; } int nid = next_nid++; - f << stringf("%d %s %d %d %d ; %s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, log_id(cell)); + btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); SigSpec sig = sigmap(cell->getPort("\\Y")); @@ -154,7 +181,7 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig)); int zeros_nid = get_sig_nid(Const(0, GetSize(sig)-1)); int nid2 = next_nid++; - f << stringf("%d concat %d %d %d ; %s\n", nid2, sid, zeros_nid, nid, log_id(cell)); + btorf("%d concat %d %d %d\n", nid2, sid, zeros_nid, nid); nid = nid2; } @@ -175,7 +202,7 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig_y)); int nid = next_nid++; - f << stringf("%d ite %d %d %d %d ; %s\n", nid, sid, nid_s, nid_b, nid_a, log_id(cell)); + btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a); add_nid_sig(nid, sig_y); goto okay; @@ -195,9 +222,13 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig_q)); int nid = next_nid++; - f << stringf("%d state %d %s ; %s\n", nid, sid, symbol.c_str(), log_id(cell)); - ff_todo.push_back(make_pair(nid, sig_d)); + if (output_symbols.count(symbol)) + btorf("%d state %d\n", nid, sid); + else + btorf("%d state %d %s\n", nid, sid, symbol.c_str()); + + ff_todo.push_back(make_pair(nid, cell)); add_nid_sig(nid, sig_q); goto okay; } @@ -212,9 +243,9 @@ struct BtorWorker int one_nid = get_sig_nid(Const(1, 1)); int zero_nid = get_sig_nid(Const(0, 1)); initstate_nid = next_nid++; - f << stringf("%d state %d ; initstate\n", initstate_nid, sid); - f << stringf("%d init %d %d %d ; initstate\n", next_nid++, sid, initstate_nid, one_nid); - f << stringf("%d next %d %d %d ; initstate\n", next_nid++, sid, initstate_nid, zero_nid); + btorf("%d state %d\n", initstate_nid, sid); + btorf("%d init %d %d %d\n", next_nid++, sid, initstate_nid, one_nid); + btorf("%d next %d %d %d\n", next_nid++, sid, initstate_nid, zero_nid); } add_nid_sig(initstate_nid, sig_y); @@ -224,6 +255,7 @@ struct BtorWorker log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); okay: + btorf_pop(log_id(cell)); cell_recursion_guard.erase(cell); } @@ -253,7 +285,7 @@ struct BtorWorker if (consts.count(c) == 0) { int sid = get_bv_sid(GetSize(c)); int nid = next_nid++; - f << stringf("%d const %d %s\n", nid, sid, c.as_string().c_str()); + btorf("%d const %d %s\n", nid, sid, c.as_string().c_str()); consts[c] = nid; nid_width[nid] = GetSize(c); } @@ -295,7 +327,7 @@ struct BtorWorker if (lower != 0 || upper+1 != nid_width.at(nid2)) { int sid = get_bv_sid(upper-lower+1); nid3 = next_nid++; - f << stringf("%d slice %d %d %d %d\n", nid3, sid, nid2, upper, lower); + btorf("%d slice %d %d %d %d\n", nid3, sid, nid2, upper, lower); } int nid4 = nid3; @@ -303,7 +335,7 @@ struct BtorWorker if (nid >= 0) { int sid = get_bv_sid(width+upper-lower+1); int nid4 = next_nid++; - f << stringf("%d concat %d %d %d\n", nid4, sid, nid, nid3); + btorf("%d concat %d %d %d\n", nid4, sid, nid, nid3); } width += upper-lower+1; @@ -322,14 +354,14 @@ struct BtorWorker { int sid = get_bv_sid(to_width); int nid2 = next_nid++; - f << stringf("%d slice %d %d %d 0\n", nid2, sid, nid, to_width-1); + btorf("%d slice %d %d %d 0\n", nid2, sid, nid, to_width-1); nid = nid2; } else { int sid = get_bv_sid(to_width); int nid2 = next_nid++; - f << stringf("%d %s %d %d %d\n", nid2, is_signed ? "sext" : "uext", + btorf("%d %s %d %d %d\n", nid2, is_signed ? "sext" : "uext", sid, nid, to_width - GetSize(sig)); nid = nid2; } @@ -341,6 +373,8 @@ struct BtorWorker BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose) : f(f), sigmap(module), module(module), verbose(verbose) { + btorf_push("inputs"); + for (auto wire : module->wires()) { if (!wire->port_id || !wire->port_input) @@ -350,10 +384,12 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig)); int nid = next_nid++; - f << stringf("%d input %d %s\n", nid, sid, log_id(wire)); + btorf("%d input %d %s\n", nid, sid, log_id(wire)); add_nid_sig(nid, sig); } + btorf_pop("inputs"); + for (auto cell : module->cells()) for (auto &conn : cell->connections()) { @@ -364,19 +400,29 @@ struct BtorWorker bit_cell[bit] = cell; } + for (auto wire : module->wires()) + if (wire->port_output) + output_symbols.insert(log_id(wire)); + for (auto wire : module->wires()) { if (!wire->port_id || !wire->port_output) continue; + btorf_push(stringf("output %s", log_id(wire))); + int nid = get_sig_nid(wire); - f << stringf("%d output %d %s\n", next_nid++, nid, log_id(wire)); + btorf("%d output %d %s\n", next_nid++, nid, log_id(wire)); + + btorf_pop(stringf("output %s", log_id(wire))); } for (auto cell : module->cells()) { if (cell->type == "$assume") { + btorf_push(log_id(cell)); + int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort("\\A")); int nid_en = get_sig_nid(cell->getPort("\\EN")); @@ -384,13 +430,17 @@ struct BtorWorker int nid_a_or_not_en = next_nid++; int nid = next_nid++; - f << stringf("%d not %d %d\n", nid_not_en, sid, nid_en); - f << stringf("%d or %d %d %d\n", nid_a_or_not_en, sid, nid_a, nid_not_en); - f << stringf("%d constraint %d ; %s\n", nid, nid_a_or_not_en, log_id(cell)); + btorf("%d not %d %d\n", nid_not_en, sid, nid_en); + btorf("%d or %d %d %d\n", nid_a_or_not_en, sid, nid_a, nid_not_en); + btorf("%d constraint %d\n", nid, nid_a_or_not_en); + + btorf_pop(log_id(cell)); } if (cell->type == "$assert") { + btorf_push(log_id(cell)); + int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort("\\A")); int nid_en = get_sig_nid(cell->getPort("\\EN")); @@ -398,22 +448,30 @@ struct BtorWorker int nid_en_and_not_a = next_nid++; int nid = next_nid++; - f << stringf("%d not %d %d\n", nid_not_a, sid, nid_a); - f << stringf("%d and %d %d %d\n", nid_en_and_not_a, sid, nid_en, nid_not_a); - f << stringf("%d bad %d ; %s\n", nid, nid_en_and_not_a, log_id(cell)); + btorf("%d not %d %d\n", nid_not_a, sid, nid_a); + btorf("%d and %d %d %d\n", nid_en_and_not_a, sid, nid_en, nid_not_a); + btorf("%d bad %d\n", nid, nid_en_and_not_a); + + btorf_pop(log_id(cell)); } } while (!ff_todo.empty()) { - vector> todo; + vector> todo; todo.swap(ff_todo); for (auto &it : todo) { - int nid = get_sig_nid(it.second); - int sid = get_bv_sid(GetSize(it.second)); - f << stringf("%d next %d %d %d\n", next_nid++, sid, it.first, nid); + btorf_push(stringf("next %s", log_id(it.second))); + + SigSpec sig = sigmap(it.second->getPort("\\D")); + + int nid = get_sig_nid(sig); + int sid = get_bv_sid(GetSize(sig)); + btorf("%d next %d %d %d\n", next_nid++, sid, it.first, nid); + + btorf_pop(stringf("next %s", log_id(it.second))); } } } @@ -429,6 +487,9 @@ struct BtorBackend : public Backend { log("\n"); log("Write a BTOR description of the current design.\n"); log("\n"); + log(" -v\n"); + log(" Add comments and indentation to BTOR output file\n"); + log("\n"); } virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) { @@ -439,10 +500,10 @@ struct BtorBackend : public Backend { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - // if (args[argidx] == "-verbose") { - // verbose = true; - // continue; - // } + if (args[argidx] == "-v") { + verbose = true; + continue; + } break; } extra_args(f, filename, args, argidx); From e3a51b3e876e1bf41cf2e66d66a0e793b8e658d6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 24 Nov 2017 18:13:41 +0100 Subject: [PATCH 07/19] Bugfixes in new BTOR back-end --- backends/btor/btor.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 2a98d1aba..51715ff25 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -334,7 +334,7 @@ struct BtorWorker if (nid >= 0) { int sid = get_bv_sid(width+upper-lower+1); - int nid4 = next_nid++; + nid4 = next_nid++; btorf("%d concat %d %d %d\n", nid4, sid, nid, nid3); } @@ -411,8 +411,9 @@ struct BtorWorker btorf_push(stringf("output %s", log_id(wire))); + int sid = get_bv_sid(GetSize(wire)); int nid = get_sig_nid(wire); - btorf("%d output %d %s\n", next_nid++, nid, log_id(wire)); + btorf("%d output %d %d %s\n", next_nid++, sid, nid, log_id(wire)); btorf_pop(stringf("output %s", log_id(wire))); } From b981e5aa6904954dbb89a0d1321f65719601c029 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 27 Nov 2017 17:42:32 +0100 Subject: [PATCH 08/19] Fixed "yosys-smtbmc -g" handling of no solution --- backends/smt2/smtbmc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index d9b79e26e..560e39d86 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -1279,7 +1279,7 @@ else: # not tempind, covermode step += step_size - if gentrace: + if gentrace and retstatus: print_anyconsts(0) write_trace(0, num_steps, '%') From 63343aeaaa96d947695ac624f7942cc60b0e9e0f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 9 Dec 2017 05:58:14 +0100 Subject: [PATCH 09/19] Fix btor concat --- backends/btor/btor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 51715ff25..80ff4eedf 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -335,7 +335,7 @@ struct BtorWorker if (nid >= 0) { int sid = get_bv_sid(width+upper-lower+1); nid4 = next_nid++; - btorf("%d concat %d %d %d\n", nid4, sid, nid, nid3); + btorf("%d concat %d %d %d\n", nid4, sid, nid3, nid); } width += upper-lower+1; From 83cf7363096ba1454c2f7cc810df808a96794d82 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 10 Dec 2017 07:16:47 +0100 Subject: [PATCH 10/19] Add support for more cell types to btor back-end --- backends/btor/btor.cc | 221 +++++++++++++++++++++++++++++++++++- backends/btor/test_cells.sh | 30 +++++ 2 files changed, 245 insertions(+), 6 deletions(-) create mode 100644 backends/btor/test_cells.sh diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 80ff4eedf..768ff0292 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -114,12 +114,21 @@ struct BtorWorker cell_recursion_guard.insert(cell); btorf_push(log_id(cell)); - if (cell->type.in("$add", "$sub", "$xor")) + if (cell->type.in("$add", "$sub", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", + "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) { string btor_op; if (cell->type == "$add") btor_op = "add"; if (cell->type == "$sub") btor_op = "sub"; - if (cell->type == "$xor") btor_op = "xor"; + if (cell->type.in("$shl", "$sshl")) btor_op = "sll"; + if (cell->type == "$shr") btor_op = "srl"; + if (cell->type == "$sshr") btor_op = "sra"; + if (cell->type.in("$and", "$_AND_")) btor_op = "and"; + if (cell->type.in("$or", "$_OR_")) btor_op = "or"; + if (cell->type.in("$xor", "$_XOR_")) btor_op = "xor"; + if (cell->type == "$_NAND_") btor_op = "nand"; + if (cell->type == "$_NOR_") btor_op = "nor"; + if (cell->type.in("$xnor", "$_XNOR_")) btor_op = "xnor"; log_assert(!btor_op.empty()); int width = GetSize(cell->getPort("\\Y")); @@ -129,6 +138,11 @@ struct BtorWorker bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; + if (cell->type.in("$shl", "$shr")) { + a_signed = false; + b_signed = false; + } + int sid = get_bv_sid(width); int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); @@ -149,16 +163,174 @@ struct BtorWorker goto okay; } - if (cell->type.in("$logic_and", "$logic_or")) + if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) + { + int sid = get_bv_sid(1); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_b = get_sig_nid(cell->getPort("\\B")); + + int nid1 = next_nid++; + int nid2 = next_nid++; + + if (cell->type == "$_ANDNOT_") { + btorf("%d not %d %d\n", nid1, sid, nid_b); + btorf("%d and %d %d %d\n", nid2, sid, nid_a, nid1); + } + + if (cell->type == "$_ORNOT_") { + btorf("%d not %d %d\n", nid1, sid, nid_b); + btorf("%d or %d %d %d\n", nid2, sid, nid_a, nid1); + } + + SigSpec sig = sigmap(cell->getPort("\\Y")); + add_nid_sig(nid2, sig); + goto okay; + } + + if (cell->type.in("$_OAI3_", "$_AOI3_")) + { + int sid = get_bv_sid(1); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_b = get_sig_nid(cell->getPort("\\B")); + int nid_c = get_sig_nid(cell->getPort("\\C")); + + int nid1 = next_nid++; + int nid2 = next_nid++; + int nid3 = next_nid++; + + if (cell->type == "$_OAI3_") { + btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b); + btorf("%d and %d %d %d\n", nid2, sid, nid1, nid_c); + btorf("%d not %d %d\n", nid3, sid, nid2); + } + + if (cell->type == "$_AOI3_") { + btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b); + btorf("%d or %d %d %d\n", nid2, sid, nid1, nid_c); + btorf("%d not %d %d\n", nid3, sid, nid2); + } + + SigSpec sig = sigmap(cell->getPort("\\Y")); + add_nid_sig(nid3, sig); + goto okay; + } + + if (cell->type.in("$_OAI4_", "$_AOI4_")) + { + int sid = get_bv_sid(1); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_b = get_sig_nid(cell->getPort("\\B")); + int nid_c = get_sig_nid(cell->getPort("\\C")); + int nid_d = get_sig_nid(cell->getPort("\\D")); + + int nid1 = next_nid++; + int nid2 = next_nid++; + int nid3 = next_nid++; + int nid4 = next_nid++; + + if (cell->type == "$_OAI4_") { + btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b); + btorf("%d or %d %d %d\n", nid2, sid, nid_c, nid_d); + btorf("%d and %d %d %d\n", nid3, sid, nid1, nid2); + btorf("%d not %d %d\n", nid4, sid, nid3); + } + + if (cell->type == "$_AOI4_") { + btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b); + btorf("%d and %d %d %d\n", nid2, sid, nid_c, nid_d); + btorf("%d or %d %d %d\n", nid3, sid, nid1, nid2); + btorf("%d not %d %d\n", nid4, sid, nid3); + } + + SigSpec sig = sigmap(cell->getPort("\\Y")); + add_nid_sig(nid4, sig); + goto okay; + } + + if (cell->type.in("$lt", "$le", "$eq", "$eqx", "$ne", "$nex", "$ge", "$gt")) + { + string btor_op; + if (cell->type == "$lt") btor_op = "lt"; + if (cell->type == "$le") btor_op = "lte"; + if (cell->type.in("$eq", "$eqx")) btor_op = "eq"; + if (cell->type.in("$ne", "$nex")) btor_op = "ne"; + if (cell->type == "$ge") btor_op = "gte"; + if (cell->type == "$gt") btor_op = "gt"; + log_assert(!btor_op.empty()); + + int width = 1; + width = std::max(width, GetSize(cell->getPort("\\A"))); + width = std::max(width, GetSize(cell->getPort("\\B"))); + + bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; + bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; + + int sid = get_bv_sid(1); + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); + + int nid = next_nid++; + if (cell->type.in("$lt", "$le", "$ge", "$gt")) { + btorf("%d %c%s %d %d %d\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b); + } else { + btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); + } + + SigSpec sig = sigmap(cell->getPort("\\Y")); + + if (GetSize(sig) > 1) { + int sid = get_bv_sid(GetSize(sig)); + int nid2 = next_nid++; + btorf("%d uext %d %d %d\n", nid2, sid, nid, GetSize(sig) - 1); + nid = nid2; + } + + add_nid_sig(nid, sig); + goto okay; + } + + if (cell->type.in("$not", "$neg", "$_NOT_")) + { + string btor_op; + if (cell->type.in("$not", "$_NOT_")) btor_op = "not"; + if (cell->type == "$neg") btor_op = "neg"; + log_assert(!btor_op.empty()); + + int width = GetSize(cell->getPort("\\Y")); + width = std::max(width, GetSize(cell->getPort("\\A"))); + + bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; + + int sid = get_bv_sid(width); + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); + + int nid = next_nid++; + btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a); + + SigSpec sig = sigmap(cell->getPort("\\Y")); + + if (GetSize(sig) < width) { + int sid = get_bv_sid(GetSize(sig)); + int nid2 = next_nid++; + btorf("%d slice %d %d %d 0\n", nid2, sid, nid, GetSize(sig)-1); + nid = nid2; + } + + add_nid_sig(nid, sig); + goto okay; + } + + if (cell->type.in("$logic_and", "$logic_or", "$logic_not")) { string btor_op; if (cell->type == "$logic_and") btor_op = "and"; if (cell->type == "$logic_or") btor_op = "or"; + if (cell->type == "$logic_not") btor_op = "not"; log_assert(!btor_op.empty()); int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort("\\A")); - int nid_b = get_sig_nid(cell->getPort("\\B")); + int nid_b = btor_op != "not" ? get_sig_nid(cell->getPort("\\B")) : 0; if (GetSize(cell->getPort("\\A")) > 1) { int nid_red_a = next_nid++; @@ -166,14 +338,51 @@ struct BtorWorker nid_a = nid_red_a; } - if (GetSize(cell->getPort("\\B")) > 1) { + if (btor_op != "not" && GetSize(cell->getPort("\\B")) > 1) { int nid_red_b = next_nid++; btorf("%d redor %d %d\n", nid_red_b, sid, nid_b); nid_b = nid_red_b; } int nid = next_nid++; - btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); + if (btor_op != "not") + btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); + else + btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a); + + SigSpec sig = sigmap(cell->getPort("\\Y")); + + if (GetSize(sig) > 1) { + int sid = get_bv_sid(GetSize(sig)); + int zeros_nid = get_sig_nid(Const(0, GetSize(sig)-1)); + int nid2 = next_nid++; + btorf("%d concat %d %d %d\n", nid2, sid, zeros_nid, nid); + nid = nid2; + } + + add_nid_sig(nid, sig); + goto okay; + } + + if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor")) + { + string btor_op; + if (cell->type == "$reduce_and") btor_op = "redand"; + if (cell->type.in("$reduce_or", "$reduce_bool")) btor_op = "redor"; + if (cell->type.in("$reduce_xor", "$reduce_xnor")) btor_op = "redxor"; + log_assert(!btor_op.empty()); + + int sid = get_bv_sid(1); + int nid_a = get_sig_nid(cell->getPort("\\A")); + + int nid = next_nid++; + btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a); + + if (cell->type == "$reduce_xnor") { + int nid2 = next_nid++; + btorf("%d not %d %d %d\n", nid2, sid, nid); + nid = nid2; + } SigSpec sig = sigmap(cell->getPort("\\Y")); diff --git a/backends/btor/test_cells.sh b/backends/btor/test_cells.sh new file mode 100644 index 000000000..c3572bc93 --- /dev/null +++ b/backends/btor/test_cells.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -ex + +rm -rf test_cells.tmp +mkdir -p test_cells.tmp +cd test_cells.tmp + +../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod /$shl /$shr /$sshl /$sshr /$shift /$shiftx' + +for fn in test_*.il; do + ../../../yosys -p " + read_ilang $fn + rename gold gate + synth + + read_ilang $fn + miter -equiv -make_assert -flatten gold gate main + hierarchy -top main + write_btor ${fn%.il}.btor + " + boolectormc -v ${fn%.il}.btor > ${fn%.il}.out + if grep " SATISFIABLE" ${fn%.il}.out; then + echo "Check failed for ${fn%.il}." + exit 1 + fi +done + +echo "OK." + From 133a0f497865c76e3e9c42ced93eb7f5d349ade6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 10 Dec 2017 08:11:08 +0100 Subject: [PATCH 11/19] Add support for $pmux in btor back-end --- backends/btor/btor.cc | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 768ff0292..6e8da4707 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -417,6 +417,29 @@ struct BtorWorker goto okay; } + if (cell->type == "$pmux") + { + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); + SigSpec sig_s = sigmap(cell->getPort("\\S")); + SigSpec sig_y = sigmap(cell->getPort("\\Y")); + + int width = GetSize(sig_a); + int sid = get_bv_sid(width); + int nid = get_sig_nid(sig_a); + + for (int i = 0; i < GetSize(sig_s); i++) { + int nid_b = get_sig_nid(sig_b.extract(i*width, width)); + int nid_s = get_sig_nid(sig_s.extract(i)); + int nid2 = next_nid++; + btorf("%d ite %d %d %d %d\n", nid2, sid, nid_s, nid_b, nid); + nid = nid2; + } + + add_nid_sig(nid, sig_y); + goto okay; + } + if (cell->type.in("$dff", "$ff", "$_DFF_P_", "$_DFF_N", "$_FF_")) { SigSpec sig_d = sigmap(cell->getPort("\\D")); From cc119b5232a7f9aa201595d32b08e4e6f519dd3c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 10 Dec 2017 08:40:11 +0100 Subject: [PATCH 12/19] Fix btor back-end shift handling --- backends/btor/btor.cc | 10 ++++++---- backends/btor/test_cells.sh | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 6e8da4707..cd6430090 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -114,7 +114,7 @@ struct BtorWorker cell_recursion_guard.insert(cell); btorf_push(log_id(cell)); - if (cell->type.in("$add", "$sub", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", + if (cell->type.in("$add", "$sub", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) { string btor_op; @@ -123,6 +123,7 @@ struct BtorWorker if (cell->type.in("$shl", "$sshl")) btor_op = "sll"; if (cell->type == "$shr") btor_op = "srl"; if (cell->type == "$sshr") btor_op = "sra"; + // if (cell->type.in("$shift", "$shiftx")) btor_op = "shift"; if (cell->type.in("$and", "$_AND_")) btor_op = "and"; if (cell->type.in("$or", "$_OR_")) btor_op = "or"; if (cell->type.in("$xor", "$_XOR_")) btor_op = "xor"; @@ -138,10 +139,11 @@ struct BtorWorker bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; - if (cell->type.in("$shl", "$shr")) { - a_signed = false; + if (cell->type.in("$shl", "$sshl", "$shr", "$sshr")) b_signed = false; - } + + if (cell->type == "$sshr" && !a_signed) + btor_op = "srl"; int sid = get_bv_sid(width); int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); diff --git a/backends/btor/test_cells.sh b/backends/btor/test_cells.sh index c3572bc93..0dc8ad854 100644 --- a/backends/btor/test_cells.sh +++ b/backends/btor/test_cells.sh @@ -6,7 +6,7 @@ rm -rf test_cells.tmp mkdir -p test_cells.tmp cd test_cells.tmp -../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod /$shl /$shr /$sshl /$sshr /$shift /$shiftx' +../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod /$shift /$shiftx' for fn in test_*.il; do ../../../yosys -p " From 82d1fd77de31aece7b8a4f31fa53cb9dda2ec5f6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 11 Dec 2017 14:24:19 +0100 Subject: [PATCH 13/19] Add btor $shift/$shiftx support --- backends/btor/btor.cc | 40 ++++++++++++++++++++++++++++++++----- backends/btor/test_cells.sh | 4 ++-- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index cd6430090..7b80427b8 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -123,7 +123,7 @@ struct BtorWorker if (cell->type.in("$shl", "$sshl")) btor_op = "sll"; if (cell->type == "$shr") btor_op = "srl"; if (cell->type == "$sshr") btor_op = "sra"; - // if (cell->type.in("$shift", "$shiftx")) btor_op = "shift"; + if (cell->type.in("$shift", "$shiftx")) btor_op = "shift"; if (cell->type.in("$and", "$_AND_")) btor_op = "and"; if (cell->type.in("$or", "$_OR_")) btor_op = "or"; if (cell->type.in("$xor", "$_XOR_")) btor_op = "xor"; @@ -139,6 +139,9 @@ struct BtorWorker bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; + if (btor_op == "shift" && !b_signed) + btor_op = "srl"; + if (cell->type.in("$shl", "$sshl", "$shr", "$sshr")) b_signed = false; @@ -146,11 +149,38 @@ struct BtorWorker btor_op = "srl"; int sid = get_bv_sid(width); - int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); - int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); + int nid; - int nid = next_nid++; - btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); + if (btor_op == "shift") + { + int nid_a = get_sig_nid(cell->getPort("\\A"), width, false); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); + + int nid_r = next_nid++; + btorf("%d srl %d %d %d\n", nid_r, sid, nid_a, nid_b); + + int nid_b_neg = next_nid++; + btorf("%d neg %d %d\n", nid_b_neg, sid, nid_b); + + int nid_l = next_nid++; + btorf("%d sll %d %d %d\n", nid_l, sid, nid_a, nid_b_neg); + + int sid_bit = get_bv_sid(1); + int nid_zero = get_sig_nid(Const(0, width)); + int nid_b_ltz = next_nid++; + btorf("%d slt %d %d %d\n", nid_b_ltz, sid_bit, nid_b, nid_zero); + + nid = next_nid++; + btorf("%d ite %d %d %d %d\n", nid, sid, nid_b_ltz, nid_l, nid_r); + } + else + { + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); + + nid = next_nid++; + btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); + } SigSpec sig = sigmap(cell->getPort("\\Y")); diff --git a/backends/btor/test_cells.sh b/backends/btor/test_cells.sh index 0dc8ad854..e0f1a0514 100644 --- a/backends/btor/test_cells.sh +++ b/backends/btor/test_cells.sh @@ -6,7 +6,7 @@ rm -rf test_cells.tmp mkdir -p test_cells.tmp cd test_cells.tmp -../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod /$shift /$shiftx' +../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod' for fn in test_*.il; do ../../../yosys -p " @@ -19,7 +19,7 @@ for fn in test_*.il; do hierarchy -top main write_btor ${fn%.il}.btor " - boolectormc -v ${fn%.il}.btor > ${fn%.il}.out + boolectormc -kmax 1 --trace-gen --stop-first -v ${fn%.il}.btor > ${fn%.il}.out if grep " SATISFIABLE" ${fn%.il}.out; then echo "Check failed for ${fn%.il}." exit 1 From 2b6307547f37c219a67fea6345249615aaa5fc9a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Dec 2017 21:48:31 +0100 Subject: [PATCH 14/19] Add SigSpec::is_fully_ones() --- kernel/rtlil.cc | 15 +++++++++++++++ kernel/rtlil.h | 1 + 2 files changed, 16 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 8c3d2962c..7dc7107c1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3353,6 +3353,21 @@ bool RTLIL::SigSpec::is_fully_zero() const return true; } +bool RTLIL::SigSpec::is_fully_ones() const +{ + cover("kernel.rtlil.sigspec.is_fully_ones"); + + pack(); + for (auto it = chunks_.begin(); it != chunks_.end(); it++) { + if (it->width > 0 && it->wire != NULL) + return false; + for (size_t i = 0; i < it->data.size(); i++) + if (it->data[i] != RTLIL::State::S1) + return false; + } + return true; +} + bool RTLIL::SigSpec::is_fully_def() const { cover("kernel.rtlil.sigspec.is_fully_def"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 6ce9b6748..b33cb53a3 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -704,6 +704,7 @@ public: bool is_fully_const() const; bool is_fully_zero() const; + bool is_fully_ones() const; bool is_fully_def() const; bool is_fully_undef() const; bool has_const() const; From f697282246862d99ae5c1798456c9082c615cea2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Dec 2017 21:48:55 +0100 Subject: [PATCH 15/19] Add btor back-end support for 'x' constants --- backends/btor/btor.cc | 55 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 7b80427b8..d2deb50b8 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -525,8 +525,60 @@ struct BtorWorker int get_sig_nid(SigSpec sig, int to_width = -1, bool is_signed = false) { + int nid = -1; sigmap.apply(sig); + for (auto bit : sig) + if (bit == State::Sx) + goto has_undef_bits; + + if (0) + { + has_undef_bits: + SigSpec sig_mask_undef, sig_noundef; + int first_undef = -1; + + for (int i = 0; i < GetSize(sig); i++) + if (sig[i] == State::Sx) { + if (first_undef < 0) + first_undef = i; + sig_mask_undef.append(State::S1); + sig_noundef.append(State::S0); + } else { + sig_mask_undef.append(State::S0); + sig_noundef.append(sig[i]); + } + + if (to_width < 0 || first_undef < to_width) + { + int sid = get_bv_sid(GetSize(sig)); + + int nid_input = next_nid++; + btorf("%d input %d\n", nid_input, sid); + + int nid_masked_input; + if (sig_mask_undef.is_fully_ones()) { + nid_masked_input = nid_input; + } else { + int nid_mask_undef = get_sig_nid(sig_mask_undef); + nid_masked_input = next_nid++; + btorf("%d and %d %d %d\n", nid_masked_input, sid, nid_input, nid_mask_undef); + } + + if (sig_noundef.is_fully_zero()) { + nid = nid_masked_input; + } else { + int nid_noundef = get_sig_nid(sig_noundef); + nid = next_nid++; + btorf("%d or %d %d %d\n", nid, sid, nid_masked_input, nid_noundef); + } + + goto extend_or_trim; + } + + sig = sig_noundef; + } + if (sig_nid.count(sig) == 0) { // , @@ -610,8 +662,9 @@ struct BtorWorker nid_width[nid] = width; } - int nid = sig_nid.at(sig); + nid = sig_nid.at(sig); + extend_or_trim: if (to_width >= 0 && to_width != GetSize(sig)) { if (to_width < GetSize(sig)) From 0881bbf2e711a23137e860bf1dfc2c6130d3d07b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Dec 2017 23:43:55 +0100 Subject: [PATCH 16/19] Add state initval handling to btor back-end --- backends/btor/btor.cc | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index d2deb50b8..56d17c6e9 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -63,6 +63,7 @@ struct BtorWorker pool cell_recursion_guard; pool output_symbols; + dict initbits; string indent; void btorf(const char *fmt, ...) @@ -101,6 +102,9 @@ struct BtorWorker void add_nid_sig(int nid, const SigSpec &sig) { + if (verbose) + f << indent << stringf("; %d %s\n", nid, log_signal(sig)); + for (int i = 0; i < GetSize(sig); i++) bit_nid[sig[i]] = make_pair(nid, i); @@ -492,6 +496,20 @@ struct BtorWorker else btorf("%d state %d %s\n", nid, sid, symbol.c_str()); + Const initval; + for (int i = 0; i < GetSize(sig_q); i++) + if (initbits.count(sig_q[i])) + initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0); + else + initval.bits.push_back(State::Sx); + + if (!initval.is_fully_undef()) { + int nid_init_val = get_sig_nid(initval); + int nid_init = next_nid++; + btorf("; initval = %s\n", log_signal(initval)); + btorf("%d init %d %d %d\n", nid_init, sid, nid, nid_init_val); + } + ff_todo.push_back(make_pair(nid, cell)); add_nid_sig(nid, sig_q); goto okay; @@ -694,6 +712,13 @@ struct BtorWorker for (auto wire : module->wires()) { + if (wire->attributes.count("\\init")) { + Const attrval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(wire) && i < GetSize(attrval); i++) + if (attrval[i] == State::S0 || attrval[i] == State::S1) + initbits[sigmap(SigBit(wire, i))] = (attrval[i] == State::S1); + } + if (!wire->port_id || !wire->port_input) continue; From 546de7fa4fbd1b54e125fac06b588dbecfb033e0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 13 Dec 2017 00:15:44 +0100 Subject: [PATCH 17/19] Add "write_btor -s" mode --- backends/btor/btor.cc | 56 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 56d17c6e9..b5e6ae96c 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -33,6 +33,7 @@ struct BtorWorker SigMap sigmap; RTLIL::Module *module; bool verbose; + bool single_bad; int next_nid = 1; int initstate_nid = -1; @@ -63,6 +64,7 @@ struct BtorWorker pool cell_recursion_guard; pool output_symbols; + vector bad_properties; dict initbits; string indent; @@ -705,8 +707,8 @@ struct BtorWorker return nid; } - BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose) : - f(f), sigmap(module), module(module), verbose(verbose) + BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose, bool single_bad) : + f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad) { btorf_push("inputs"); @@ -789,11 +791,16 @@ struct BtorWorker int nid_en = get_sig_nid(cell->getPort("\\EN")); int nid_not_a = next_nid++; int nid_en_and_not_a = next_nid++; - int nid = next_nid++; btorf("%d not %d %d\n", nid_not_a, sid, nid_a); btorf("%d and %d %d %d\n", nid_en_and_not_a, sid, nid_en, nid_not_a); - btorf("%d bad %d\n", nid, nid_en_and_not_a); + + if (single_bad) { + bad_properties.push_back(nid_en_and_not_a); + } else { + int nid = next_nid++; + btorf("%d bad %d\n", nid, nid_en_and_not_a); + } btorf_pop(log_id(cell)); } @@ -817,6 +824,36 @@ struct BtorWorker btorf_pop(stringf("next %s", log_id(it.second))); } } + + while (!bad_properties.empty()) + { + vector todo; + bad_properties.swap(todo); + + int sid = get_bv_sid(1); + int cursor = 0; + + while (cursor+1 < GetSize(todo)) + { + int nid_a = todo[cursor++]; + int nid_b = todo[cursor++]; + int nid = next_nid++; + + bad_properties.push_back(nid); + btorf("%d or %d %d %d\n", nid, sid, nid_a, nid_b); + } + + if (!bad_properties.empty()) { + if (cursor < GetSize(todo)) + bad_properties.push_back(todo[cursor++]); + log_assert(cursor == GetSize(todo)); + } else { + int nid = next_nid++; + log_assert(cursor == 0); + log_assert(GetSize(todo) == 1); + btorf("%d bad %d\n", nid, todo[cursor]); + } + } } }; @@ -833,10 +870,13 @@ struct BtorBackend : public Backend { log(" -v\n"); log(" Add comments and indentation to BTOR output file\n"); log("\n"); + log(" -s\n"); + log(" Output only a single bad property for all asserts\n"); + log("\n"); } virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) { - bool verbose = false; + bool verbose = false, single_bad = false; log_header(design, "Executing BTOR backend.\n"); @@ -847,6 +887,10 @@ struct BtorBackend : public Backend { verbose = true; continue; } + if (args[argidx] == "-s") { + single_bad = true; + continue; + } break; } extra_args(f, filename, args, argidx); @@ -859,7 +903,7 @@ struct BtorBackend : public Backend { *f << stringf("; BTOR description generated by %s for module %s.\n", yosys_version_str, log_id(topmod)); - BtorWorker(*f, topmod, verbose); + BtorWorker(*f, topmod, verbose, single_bad); *f << stringf("; end of yosys output\n"); } From ad901671c54e5dfa9292a9bdf97cedab64a7c229 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 15 Dec 2017 00:40:24 +0100 Subject: [PATCH 18/19] Add $anyconst/$anyseq support to btor back-end --- backends/btor/btor.cc | 64 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index b5e6ae96c..2411c4784 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -63,9 +63,9 @@ struct BtorWorker vector> ff_todo; pool cell_recursion_guard; - pool output_symbols; vector bad_properties; dict initbits; + pool statewires; string indent; void btorf(const char *fmt, ...) @@ -483,20 +483,23 @@ struct BtorWorker SigSpec sig_d = sigmap(cell->getPort("\\D")); SigSpec sig_q = sigmap(cell->getPort("\\Q")); - string symbol = log_signal(sig_q); - if (symbol.find(' ') != string::npos) - symbol = log_id(cell); + IdString symbol; - if (symbol[0] == '\\') - symbol = symbol.substr(1); + if (sig_q.is_wire()) { + Wire *w = sig_q.as_wire(); + if (w->port_id == 0) { + statewires.insert(w); + symbol = w->name; + } + } int sid = get_bv_sid(GetSize(sig_q)); int nid = next_nid++; - if (output_symbols.count(symbol)) + if (symbol.empty()) btorf("%d state %d\n", nid, sid); else - btorf("%d state %d %s\n", nid, sid, symbol.c_str()); + btorf("%d state %d %s\n", nid, sid, log_id(symbol)); Const initval; for (int i = 0; i < GetSize(sig_q); i++) @@ -508,7 +511,8 @@ struct BtorWorker if (!initval.is_fully_undef()) { int nid_init_val = get_sig_nid(initval); int nid_init = next_nid++; - btorf("; initval = %s\n", log_signal(initval)); + if (verbose) + btorf("; initval = %s\n", log_signal(initval)); btorf("%d init %d %d %d\n", nid_init, sid, nid, nid_init_val); } @@ -517,6 +521,24 @@ struct BtorWorker goto okay; } + if (cell->type.in("$anyconst", "$anyseq")) + { + SigSpec sig_y = sigmap(cell->getPort("\\Y")); + + int sid = get_bv_sid(GetSize(sig_y)); + int nid = next_nid++; + + btorf("%d state %d\n", nid, sid); + + if (cell->type == "$anyconst") { + int nid2 = next_nid++; + btorf("%d next %d %d %d\n", nid2, sid, nid, nid); + } + + add_nid_sig(nid, sig_y); + goto okay; + } + if (cell->type == "$initstate") { SigSpec sig_y = sigmap(cell->getPort("\\Y")); @@ -744,10 +766,6 @@ struct BtorWorker bit_cell[bit] = cell; } - for (auto wire : module->wires()) - if (wire->port_output) - output_symbols.insert(log_id(wire)); - for (auto wire : module->wires()) { if (!wire->port_id || !wire->port_output) @@ -806,6 +824,26 @@ struct BtorWorker } } + for (auto wire : module->wires()) + { + if (wire->port_id || wire->name[0] == '$') + continue; + + btorf_push(stringf("wire %s", log_id(wire))); + + int sid = get_bv_sid(GetSize(wire)); + int nid = get_sig_nid(sigmap(wire)); + + if (statewires.count(wire)) + continue; + + int this_nid = next_nid++; + btorf("%d uext %d %d %d %s\n", this_nid, sid, nid, 0, log_id(wire)); + + btorf_pop(stringf("wire %s", log_id(wire))); + continue; + } + while (!ff_todo.empty()) { vector> todo; From 30f23281edc19c3191fadd9d4de668a15f5e46d7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 15 Dec 2017 02:19:06 +0100 Subject: [PATCH 19/19] Add array support to btor back-end --- backends/btor/btor.cc | 175 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 169 insertions(+), 6 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 2411c4784..b0c51579c 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -102,6 +102,19 @@ struct BtorWorker return sorts_bv.at(width); } + int get_mem_sid(int abits, int dbits) + { + pair key(abits, dbits); + if (sorts_mem.count(key) == 0) { + int addr_sid = get_bv_sid(abits); + int data_sid = get_bv_sid(dbits); + int nid = next_nid++; + btorf("%d sort array %d %d\n", nid, addr_sid, data_sid); + sorts_mem[key] = nid; + } + return sorts_mem.at(key); + } + void add_nid_sig(int nid, const SigSpec &sig) { if (verbose) @@ -558,6 +571,103 @@ struct BtorWorker goto okay; } + if (cell->type == "$mem") + { + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); + int rdports = cell->getParam("\\RD_PORTS").as_int(); + int wrports = cell->getParam("\\WR_PORTS").as_int(); + + Const wr_clk_en = cell->getParam("\\WR_CLK_ENABLE"); + Const rd_clk_en = cell->getParam("\\RD_CLK_ENABLE"); + + bool asyncwr = wr_clk_en.is_fully_zero(); + + if (!asyncwr && !wr_clk_en.is_fully_ones()) + log_error("Memory %s.%s has mixed async/sync write ports.\n", + log_id(module), log_id(cell)); + + if (!rd_clk_en.is_fully_zero()) + log_error("Memory %s.%s has sync read ports.\n", + log_id(module), log_id(cell)); + + SigSpec sig_rd_addr = sigmap(cell->getPort("\\RD_ADDR")); + SigSpec sig_rd_data = sigmap(cell->getPort("\\RD_DATA")); + + SigSpec sig_wr_addr = sigmap(cell->getPort("\\WR_ADDR")); + SigSpec sig_wr_data = sigmap(cell->getPort("\\WR_DATA")); + SigSpec sig_wr_en = sigmap(cell->getPort("\\WR_EN")); + + int data_sid = get_bv_sid(width); + int sid = get_mem_sid(abits, width); + int nid = next_nid++; + int nid_head = nid; + + if (cell->name[0] == '$') + btorf("%d state %d\n", nid, sid); + else + btorf("%d state %d %s\n", nid, sid, log_id(cell)); + + if (asyncwr) + { + for (int port = 0; port < wrports; port++) + { + SigSpec wa = sig_wr_addr.extract(port*abits, abits); + SigSpec wd = sig_wr_data.extract(port*width, width); + SigSpec we = sig_wr_en.extract(port*width, width); + + int wa_nid = get_sig_nid(wa); + int wd_nid = get_sig_nid(wd); + int we_nid = get_sig_nid(we); + + int nid2 = next_nid++; + btorf("%d read %d %d %d\n", nid2, data_sid, nid_head, wa_nid); + + int nid3 = next_nid++; + btorf("%d not %d %d %d\n", nid3, data_sid, we_nid); + + int nid4 = next_nid++; + btorf("%d and %d %d %d\n", nid4, data_sid, nid2, nid3); + + int nid5 = next_nid++; + btorf("%d and %d %d %d\n", nid5, data_sid, wd_nid, we_nid); + + int nid6 = next_nid++; + btorf("%d or %d %d %d\n", nid6, data_sid, nid5, nid4); + + int nid7 = next_nid++; + btorf("%d write %d %d %d %d\n", nid7, sid, nid_head, wa_nid, nid6); + + nid_head = nid7; + } + } + + for (int port = 0; port < rdports; port++) + { + SigSpec ra = sig_rd_addr.extract(port*abits, abits); + SigSpec rd = sig_rd_data.extract(port*width, width); + + int ra_nid = get_sig_nid(ra); + int rd_nid = next_nid++; + + btorf("%d read %d %d %d\n", rd_nid, data_sid, nid_head, ra_nid); + + add_nid_sig(rd_nid, rd); + } + + if (!asyncwr) + { + ff_todo.push_back(make_pair(nid, cell)); + } + else + { + int nid2 = next_nid++; + btorf("%d next %d %d %d\n", nid2, sid, nid, nid_head); + } + + goto okay; + } + log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); okay: @@ -851,15 +961,68 @@ struct BtorWorker for (auto &it : todo) { - btorf_push(stringf("next %s", log_id(it.second))); + int nid = it.first; + Cell *cell = it.second; - SigSpec sig = sigmap(it.second->getPort("\\D")); + btorf_push(stringf("next %s", log_id(cell))); - int nid = get_sig_nid(sig); - int sid = get_bv_sid(GetSize(sig)); - btorf("%d next %d %d %d\n", next_nid++, sid, it.first, nid); + if (cell->type == "$mem") + { + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); + int wrports = cell->getParam("\\WR_PORTS").as_int(); - btorf_pop(stringf("next %s", log_id(it.second))); + SigSpec sig_wr_addr = sigmap(cell->getPort("\\WR_ADDR")); + SigSpec sig_wr_data = sigmap(cell->getPort("\\WR_DATA")); + SigSpec sig_wr_en = sigmap(cell->getPort("\\WR_EN")); + + int data_sid = get_bv_sid(width); + int sid = get_mem_sid(abits, width); + int nid_head = nid; + + for (int port = 0; port < wrports; port++) + { + SigSpec wa = sig_wr_addr.extract(port*abits, abits); + SigSpec wd = sig_wr_data.extract(port*width, width); + SigSpec we = sig_wr_en.extract(port*width, width); + + int wa_nid = get_sig_nid(wa); + int wd_nid = get_sig_nid(wd); + int we_nid = get_sig_nid(we); + + int nid2 = next_nid++; + btorf("%d read %d %d %d\n", nid2, data_sid, nid_head, wa_nid); + + int nid3 = next_nid++; + btorf("%d not %d %d %d\n", nid3, data_sid, we_nid); + + int nid4 = next_nid++; + btorf("%d and %d %d %d\n", nid4, data_sid, nid2, nid3); + + int nid5 = next_nid++; + btorf("%d and %d %d %d\n", nid5, data_sid, wd_nid, we_nid); + + int nid6 = next_nid++; + btorf("%d or %d %d %d\n", nid6, data_sid, nid5, nid4); + + int nid7 = next_nid++; + btorf("%d write %d %d %d %d\n", nid7, sid, nid_head, wa_nid, nid6); + + nid_head = nid7; + } + + int nid2 = next_nid++; + btorf("%d next %d %d %d\n", nid2, sid, nid, nid_head); + } + else + { + SigSpec sig = sigmap(cell->getPort("\\D")); + int nid_q = get_sig_nid(sig); + int sid = get_bv_sid(GetSize(sig)); + btorf("%d next %d %d %d\n", next_nid++, sid, nid, nid_q); + } + + btorf_pop(stringf("next %s", log_id(cell))); } }