mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-21 16:16:39 +00:00
Sync with upstream
This commit is contained in:
commit
5c514e00a4
3
Makefile
3
Makefile
|
@ -171,7 +171,7 @@ ifeq ($(OS), Haiku)
|
|||
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.48+57
|
||||
YOSYS_VER := 0.48+70
|
||||
|
||||
# Note: We arrange for .gitcommit to contain the (short) commit hash in
|
||||
# tarballs generated with git-archive(1) using .gitattributes. The git repo
|
||||
|
@ -933,6 +933,7 @@ endif
|
|||
SH_ABC_TEST_DIRS =
|
||||
SH_ABC_TEST_DIRS += tests/memories
|
||||
SH_ABC_TEST_DIRS += tests/aiger
|
||||
SH_ABC_TEST_DIRS += tests/alumacc
|
||||
|
||||
# seed-tests/ is a dummy string, not a directory
|
||||
.PHONY: seed-tests
|
||||
|
|
|
@ -34,6 +34,7 @@ struct JsonWriter
|
|||
bool use_selection;
|
||||
bool aig_mode;
|
||||
bool compat_int_mode;
|
||||
bool scopeinfo_mode;
|
||||
|
||||
Design *design;
|
||||
Module *module;
|
||||
|
@ -43,9 +44,9 @@ struct JsonWriter
|
|||
dict<SigBit, string> sigids;
|
||||
pool<Aig> aig_models;
|
||||
|
||||
JsonWriter(std::ostream &f, bool use_selection, bool aig_mode, bool compat_int_mode) :
|
||||
JsonWriter(std::ostream &f, bool use_selection, bool aig_mode, bool compat_int_mode, bool scopeinfo_mode) :
|
||||
f(f), use_selection(use_selection), aig_mode(aig_mode),
|
||||
compat_int_mode(compat_int_mode) { }
|
||||
compat_int_mode(compat_int_mode), scopeinfo_mode(scopeinfo_mode) { }
|
||||
|
||||
string get_string(string str)
|
||||
{
|
||||
|
@ -192,9 +193,7 @@ struct JsonWriter
|
|||
for (auto c : module->cells()) {
|
||||
if (use_selection && !module->selected(c))
|
||||
continue;
|
||||
// Eventually we will want to emit $scopeinfo, but currently this
|
||||
// will break JSON netlist consumers like nextpnr
|
||||
if (c->type == ID($scopeinfo))
|
||||
if (!scopeinfo_mode && c->type == ID($scopeinfo))
|
||||
continue;
|
||||
f << stringf("%s\n", first ? "" : ",");
|
||||
f << stringf(" %s: {\n", get_name(c->name).c_str());
|
||||
|
@ -356,6 +355,9 @@ struct JsonBackend : public Backend {
|
|||
log(" -selected\n");
|
||||
log(" output only select module\n");
|
||||
log("\n");
|
||||
log(" -noscopeinfo\n");
|
||||
log(" don't include $scopeinfo cells in the output\n");
|
||||
log("\n");
|
||||
log("\n");
|
||||
log("The general syntax of the JSON output created by this command is as follows:\n");
|
||||
log("\n");
|
||||
|
@ -601,6 +603,7 @@ struct JsonBackend : public Backend {
|
|||
bool aig_mode = false;
|
||||
bool compat_int_mode = false;
|
||||
bool use_selection = false;
|
||||
bool scopeinfo_mode = true;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
|
@ -617,13 +620,17 @@ struct JsonBackend : public Backend {
|
|||
use_selection = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-noscopeinfo") {
|
||||
scopeinfo_mode = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
||||
log_header(design, "Executing JSON backend.\n");
|
||||
|
||||
JsonWriter json_writer(*f, use_selection, aig_mode, compat_int_mode);
|
||||
JsonWriter json_writer(*f, use_selection, aig_mode, compat_int_mode, scopeinfo_mode);
|
||||
json_writer.write_design(design);
|
||||
}
|
||||
} JsonBackend;
|
||||
|
@ -648,6 +655,9 @@ struct JsonPass : public Pass {
|
|||
log(" emit 32-bit or smaller fully-defined parameter values directly\n");
|
||||
log(" as JSON numbers (for compatibility with old parsers)\n");
|
||||
log("\n");
|
||||
log(" -noscopeinfo\n");
|
||||
log(" don't include $scopeinfo cells in the output\n");
|
||||
log("\n");
|
||||
log("See 'help write_json' for a description of the JSON format used.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
@ -656,6 +666,7 @@ struct JsonPass : public Pass {
|
|||
std::string filename;
|
||||
bool aig_mode = false;
|
||||
bool compat_int_mode = false;
|
||||
bool scopeinfo_mode = true;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
|
@ -672,6 +683,10 @@ struct JsonPass : public Pass {
|
|||
compat_int_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-noscopeinfo") {
|
||||
scopeinfo_mode = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -693,7 +708,7 @@ struct JsonPass : public Pass {
|
|||
f = &buf;
|
||||
}
|
||||
|
||||
JsonWriter json_writer(*f, true, aig_mode, compat_int_mode);
|
||||
JsonWriter json_writer(*f, true, aig_mode, compat_int_mode, scopeinfo_mode);
|
||||
json_writer.write_design(design);
|
||||
|
||||
if (!empty) {
|
||||
|
|
|
@ -315,9 +315,6 @@ struct ConstEval
|
|||
Macc macc;
|
||||
macc.from_cell(cell);
|
||||
|
||||
if (!eval(macc.bit_ports, undef, cell))
|
||||
return false;
|
||||
|
||||
for (auto &port : macc.ports) {
|
||||
if (!eval(port.in_a, undef, cell))
|
||||
return false;
|
||||
|
|
|
@ -30,14 +30,11 @@ struct Macc
|
|||
RTLIL::SigSpec in_a, in_b;
|
||||
bool is_signed, do_subtract;
|
||||
};
|
||||
|
||||
std::vector<port_t> ports;
|
||||
RTLIL::SigSpec bit_ports;
|
||||
|
||||
void optimize(int width)
|
||||
{
|
||||
std::vector<port_t> new_ports;
|
||||
RTLIL::SigSpec new_bit_ports;
|
||||
RTLIL::Const off(0, width);
|
||||
|
||||
for (auto &port : ports)
|
||||
|
@ -48,11 +45,6 @@ struct Macc
|
|||
if (GetSize(port.in_a) < GetSize(port.in_b))
|
||||
std::swap(port.in_a, port.in_b);
|
||||
|
||||
if (GetSize(port.in_a) == 1 && GetSize(port.in_b) == 0 && !port.is_signed && !port.do_subtract) {
|
||||
bit_ports.append(port.in_a);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (port.in_a.is_fully_const() && port.in_b.is_fully_const()) {
|
||||
RTLIL::Const v = port.in_a.as_const();
|
||||
if (GetSize(port.in_b))
|
||||
|
@ -79,12 +71,6 @@ struct Macc
|
|||
new_ports.push_back(port);
|
||||
}
|
||||
|
||||
for (auto &bit : bit_ports)
|
||||
if (bit == State::S1)
|
||||
off = const_add(off, RTLIL::Const(1, width), false, false, width);
|
||||
else if (bit != State::S0)
|
||||
new_bit_ports.append(bit);
|
||||
|
||||
if (off.as_bool()) {
|
||||
port_t port;
|
||||
port.in_a = off;
|
||||
|
@ -94,7 +80,6 @@ struct Macc
|
|||
}
|
||||
|
||||
new_ports.swap(ports);
|
||||
bit_ports = new_bit_ports;
|
||||
}
|
||||
|
||||
void from_cell(RTLIL::Cell *cell)
|
||||
|
@ -102,7 +87,6 @@ struct Macc
|
|||
RTLIL::SigSpec port_a = cell->getPort(ID::A);
|
||||
|
||||
ports.clear();
|
||||
bit_ports = cell->getPort(ID::B);
|
||||
|
||||
auto config_bits = cell->getParam(ID::CONFIG);
|
||||
int config_cursor = 0;
|
||||
|
@ -145,6 +129,9 @@ struct Macc
|
|||
ports.push_back(this_port);
|
||||
}
|
||||
|
||||
for (auto bit : cell->getPort(ID::B))
|
||||
ports.push_back(port_t{{bit}, {}, false, false});
|
||||
|
||||
log_assert(config_cursor == config_width);
|
||||
log_assert(port_a_cursor == GetSize(port_a));
|
||||
}
|
||||
|
@ -190,11 +177,11 @@ struct Macc
|
|||
}
|
||||
|
||||
cell->setPort(ID::A, port_a);
|
||||
cell->setPort(ID::B, bit_ports);
|
||||
cell->setPort(ID::B, {});
|
||||
cell->setParam(ID::CONFIG, config_bits);
|
||||
cell->setParam(ID::CONFIG_WIDTH, GetSize(config_bits));
|
||||
cell->setParam(ID::A_WIDTH, GetSize(port_a));
|
||||
cell->setParam(ID::B_WIDTH, GetSize(bit_ports));
|
||||
cell->setParam(ID::B_WIDTH, 0);
|
||||
}
|
||||
|
||||
bool eval(RTLIL::Const &result) const
|
||||
|
@ -219,19 +206,12 @@ struct Macc
|
|||
result = const_add(result, summand, port.is_signed, port.is_signed, GetSize(result));
|
||||
}
|
||||
|
||||
for (auto bit : bit_ports) {
|
||||
if (bit.wire)
|
||||
return false;
|
||||
result = const_add(result, bit.data, false, false, GetSize(result));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_simple_product()
|
||||
{
|
||||
return bit_ports.empty() &&
|
||||
ports.size() == 1 &&
|
||||
return ports.size() == 1 &&
|
||||
!ports[0].in_b.empty() &&
|
||||
!ports[0].do_subtract;
|
||||
}
|
||||
|
|
|
@ -743,7 +743,6 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
|
|||
if (cell->type == ID($macc))
|
||||
{
|
||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||
|
||||
Macc macc;
|
||||
|
@ -785,12 +784,6 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < GetSize(b); i++) {
|
||||
std::vector<int> val(GetSize(y), ez->CONST_FALSE);
|
||||
val.at(0) = b.at(i);
|
||||
tmp = ez->vec_add(tmp, val);
|
||||
}
|
||||
|
||||
if (model_undef)
|
||||
{
|
||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/cost.h"
|
||||
|
||||
|
@ -66,7 +67,7 @@ struct ThresholdHierarchyKeeping {
|
|||
}
|
||||
|
||||
if (size > threshold) {
|
||||
log("Keeping %s (estimated size above threshold: %llu > %llu).\n", log_id(module), size, threshold);
|
||||
log("Keeping %s (estimated size above threshold: %" PRIu64 " > %" PRIu64 ").\n", log_id(module), size, threshold);
|
||||
module->set_bool_attribute(ID::keep_hierarchy);
|
||||
size = 0;
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ struct ShareWorker
|
|||
|
||||
static int bits_macc(const Macc &m, int width)
|
||||
{
|
||||
int bits = GetSize(m.bit_ports);
|
||||
int bits = 0;
|
||||
for (auto &p : m.ports)
|
||||
bits += bits_macc_port(p, width);
|
||||
return bits;
|
||||
|
@ -1255,7 +1255,6 @@ struct ShareWorker
|
|||
qcsat.max_cell_count = 100;
|
||||
}
|
||||
|
||||
pool<RTLIL::Cell*> sat_cells;
|
||||
std::set<RTLIL::SigBit> bits_queue;
|
||||
|
||||
std::vector<int> cell_active, other_cell_active;
|
||||
|
@ -1298,8 +1297,8 @@ struct ShareWorker
|
|||
|
||||
qcsat.ez->assume(qcsat.ez->AND(sub1, sub2));
|
||||
|
||||
log(" Size of SAT problem: %d cells, %d variables, %d clauses\n",
|
||||
GetSize(sat_cells), qcsat.ez->numCnfVariables(), qcsat.ez->numCnfClauses());
|
||||
log(" Size of SAT problem: %d variables, %d clauses\n",
|
||||
qcsat.ez->numCnfVariables(), qcsat.ez->numCnfClauses());
|
||||
|
||||
if (qcsat.ez->solve(sat_model, sat_model_values)) {
|
||||
log(" According to the SAT solver this pair of cells can not be shared.\n");
|
||||
|
|
|
@ -283,7 +283,7 @@ struct AlumaccWorker
|
|||
for (auto &it : sig_macc)
|
||||
{
|
||||
auto n = it.second;
|
||||
RTLIL::SigSpec A, B, C = n->macc.bit_ports;
|
||||
RTLIL::SigSpec A, B, C;
|
||||
bool a_signed = false, b_signed = false;
|
||||
bool subtract_b = false;
|
||||
alunode_t *alunode;
|
||||
|
|
|
@ -28,19 +28,25 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
IdString concat_name(RTLIL::Cell *cell, IdString object_name)
|
||||
IdString concat_name(RTLIL::Cell *cell, IdString object_name, const std::string &separator = ".")
|
||||
{
|
||||
if (object_name[0] == '\\')
|
||||
return stringf("%s.%s", cell->name.c_str(), object_name.c_str() + 1);
|
||||
return stringf("%s%s%s", cell->name.c_str(), separator.c_str(), object_name.c_str() + 1);
|
||||
else {
|
||||
return stringf("%s.%s", cell->name.c_str(), object_name.c_str());
|
||||
/*
|
||||
std::string object_name_str = object_name.str();
|
||||
if (object_name_str.substr(0, 8) == "$flatten")
|
||||
object_name_str.erase(0, 8);
|
||||
return stringf("$flatten%s%s%s", cell->name.c_str(), separator.c_str(), object_name_str.c_str());
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
IdString map_name(RTLIL::Cell *cell, T *object)
|
||||
IdString map_name(RTLIL::Cell *cell, T *object, const std::string &separator = ".")
|
||||
{
|
||||
return cell->module->uniquify(concat_name(cell, object->name));
|
||||
return cell->module->uniquify(concat_name(cell, object->name, separator));
|
||||
}
|
||||
|
||||
void map_sigspec(const dict<RTLIL::Wire*, RTLIL::Wire*> &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr)
|
||||
|
@ -57,6 +63,7 @@ struct FlattenWorker
|
|||
bool ignore_wb = false;
|
||||
bool create_scopeinfo = false; // SILIMATE: default false
|
||||
bool create_scopename = false;
|
||||
std::string separator = ".";
|
||||
|
||||
template<class T>
|
||||
void map_attributes(RTLIL::Cell *cell, T *object, IdString orig_object_name)
|
||||
|
@ -104,13 +111,13 @@ struct FlattenWorker
|
|||
}
|
||||
}
|
||||
|
||||
void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, SigMap &sigmap, std::vector<RTLIL::Cell*> &new_cells)
|
||||
void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, SigMap &sigmap, std::vector<RTLIL::Cell*> &new_cells, const std::string &separator)
|
||||
{
|
||||
// Copy the contents of the flattened cell
|
||||
|
||||
dict<IdString, IdString> memory_map;
|
||||
for (auto &tpl_memory_it : tpl->memories) {
|
||||
RTLIL::Memory *new_memory = module->addMemory(map_name(cell, tpl_memory_it.second), tpl_memory_it.second);
|
||||
RTLIL::Memory *new_memory = module->addMemory(map_name(cell, tpl_memory_it.second, separator), tpl_memory_it.second);
|
||||
map_attributes(cell, new_memory, tpl_memory_it.second->name);
|
||||
memory_map[tpl_memory_it.first] = new_memory->name;
|
||||
design->select(module, new_memory);
|
||||
|
@ -124,7 +131,7 @@ struct FlattenWorker
|
|||
|
||||
RTLIL::Wire *new_wire = nullptr;
|
||||
if (tpl_wire->name[0] == '\\') {
|
||||
RTLIL::Wire *hier_wire = module->wire(concat_name(cell, tpl_wire->name));
|
||||
RTLIL::Wire *hier_wire = module->wire(concat_name(cell, tpl_wire->name, separator));
|
||||
if (hier_wire != nullptr && hier_wire->get_bool_attribute(ID::hierconn)) {
|
||||
hier_wire->attributes.erase(ID::hierconn);
|
||||
if (GetSize(hier_wire) < GetSize(tpl_wire)) {
|
||||
|
@ -136,7 +143,7 @@ struct FlattenWorker
|
|||
}
|
||||
}
|
||||
if (new_wire == nullptr) {
|
||||
new_wire = module->addWire(map_name(cell, tpl_wire), tpl_wire);
|
||||
new_wire = module->addWire(map_name(cell, tpl_wire, separator), tpl_wire);
|
||||
new_wire->port_input = new_wire->port_output = false;
|
||||
new_wire->port_id = false;
|
||||
}
|
||||
|
@ -147,7 +154,7 @@ struct FlattenWorker
|
|||
}
|
||||
|
||||
for (auto &tpl_proc_it : tpl->processes) {
|
||||
RTLIL::Process *new_proc = module->addProcess(map_name(cell, tpl_proc_it.second), tpl_proc_it.second);
|
||||
RTLIL::Process *new_proc = module->addProcess(map_name(cell, tpl_proc_it.second, separator), tpl_proc_it.second);
|
||||
map_attributes(cell, new_proc, tpl_proc_it.second->name);
|
||||
for (auto new_proc_sync : new_proc->syncs)
|
||||
for (auto &memwr_action : new_proc_sync->mem_write_actions)
|
||||
|
@ -158,14 +165,14 @@ struct FlattenWorker
|
|||
}
|
||||
|
||||
for (auto tpl_cell : tpl->cells()) {
|
||||
RTLIL::Cell *new_cell = module->addCell(map_name(cell, tpl_cell), tpl_cell);
|
||||
RTLIL::Cell *new_cell = module->addCell(map_name(cell, tpl_cell, separator), tpl_cell);
|
||||
map_attributes(cell, new_cell, tpl_cell->name);
|
||||
if (new_cell->has_memid()) {
|
||||
IdString memid = new_cell->getParam(ID::MEMID).decode_string();
|
||||
new_cell->setParam(ID::MEMID, Const(memory_map.at(memid).str()));
|
||||
} else if (new_cell->is_mem_cell()) {
|
||||
IdString memid = new_cell->getParam(ID::MEMID).decode_string();
|
||||
new_cell->setParam(ID::MEMID, Const(concat_name(cell, memid).str()));
|
||||
new_cell->setParam(ID::MEMID, Const(concat_name(cell, memid, separator).str()));
|
||||
}
|
||||
auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec(wire_map, sig); };
|
||||
new_cell->rewrite_sigspecs(rewriter);
|
||||
|
@ -276,7 +283,7 @@ struct FlattenWorker
|
|||
module->rename(scopeinfo, cell_name);
|
||||
}
|
||||
|
||||
void flatten_module(RTLIL::Design *design, RTLIL::Module *module, pool<RTLIL::Module*> &used_modules)
|
||||
void flatten_module(RTLIL::Design *design, RTLIL::Module *module, pool<RTLIL::Module*> &used_modules, const std::string &separator)
|
||||
{
|
||||
if (!design->selected(module) || module->get_blackbox_attribute(ignore_wb))
|
||||
return;
|
||||
|
@ -305,7 +312,7 @@ struct FlattenWorker
|
|||
// If a design is fully selected and has a top module defined, topological sorting ensures that all cells
|
||||
// added during flattening are black boxes, and flattening is finished in one pass. However, when flattening
|
||||
// individual modules, this isn't the case, and the newly added cells might have to be flattened further.
|
||||
flatten_cell(design, module, cell, tpl, sigmap, worklist);
|
||||
flatten_cell(design, module, cell, tpl, sigmap, worklist, separator);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -342,6 +349,9 @@ struct FlattenPass : public Pass {
|
|||
log(" with a public name the enclosing scope can be found via their\n");
|
||||
log(" 'hdlname' attribute.\n");
|
||||
log("\n");
|
||||
log(" -separator <char>\n");
|
||||
log(" Use this separator char instead of '.' when concatenating design levels.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
|
@ -364,6 +374,10 @@ struct FlattenPass : public Pass {
|
|||
worker.create_scopename = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-separator" && argidx + 1 < args.size()) {
|
||||
worker.separator = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -398,7 +412,7 @@ struct FlattenPass : public Pass {
|
|||
log_error("Cannot flatten a design containing recursive instantiations.\n");
|
||||
|
||||
for (auto module : topo_modules.sorted)
|
||||
worker.flatten_module(design, module, used_modules);
|
||||
worker.flatten_module(design, module, used_modules, worker.separator);
|
||||
|
||||
if (top != nullptr)
|
||||
for (auto module : design->modules().to_vector())
|
||||
|
|
|
@ -286,19 +286,23 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
|
|||
log(" %s %s * %s (%dx%d bits, %s)\n", port.do_subtract ? "sub" : "add", log_signal(port.in_a), log_signal(port.in_b),
|
||||
GetSize(port.in_a), GetSize(port.in_b), port.is_signed ? "signed" : "unsigned");
|
||||
|
||||
if (GetSize(macc.bit_ports) != 0)
|
||||
log(" add bits %s (%d bits)\n", log_signal(macc.bit_ports), GetSize(macc.bit_ports));
|
||||
|
||||
if (unmap)
|
||||
{
|
||||
typedef std::pair<RTLIL::SigSpec, bool> summand_t;
|
||||
std::vector<summand_t> summands;
|
||||
|
||||
RTLIL::SigSpec bit_ports;
|
||||
|
||||
for (auto &port : macc.ports) {
|
||||
summand_t this_summand;
|
||||
if (GetSize(port.in_b)) {
|
||||
this_summand.first = module->addWire(NEW_ID, width);
|
||||
module->addMul(NEW_ID, port.in_a, port.in_b, this_summand.first, port.is_signed);
|
||||
} else if (GetSize(port.in_a) == 1 && GetSize(port.in_b) == 0 && !port.is_signed && !port.do_subtract) {
|
||||
// Mimic old 'bit_ports' treatment in case it's relevant for performance,
|
||||
// i.e. defer single-bit summands to be the last ones
|
||||
bit_ports.append(port.in_a);
|
||||
continue;
|
||||
} else if (GetSize(port.in_a) != width) {
|
||||
this_summand.first = module->addWire(NEW_ID, width);
|
||||
module->addPos(NEW_ID, port.in_a, this_summand.first, port.is_signed);
|
||||
|
@ -309,7 +313,7 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
|
|||
summands.push_back(this_summand);
|
||||
}
|
||||
|
||||
for (auto &bit : macc.bit_ports)
|
||||
for (auto &bit : bit_ports)
|
||||
summands.push_back(summand_t(bit, false));
|
||||
|
||||
if (GetSize(summands) == 0)
|
||||
|
@ -346,14 +350,20 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
|
|||
else
|
||||
{
|
||||
MaccmapWorker worker(module, width);
|
||||
RTLIL::SigSpec bit_ports;
|
||||
|
||||
for (auto &port : macc.ports)
|
||||
if (GetSize(port.in_b) == 0)
|
||||
for (auto &port : macc.ports) {
|
||||
// Mimic old 'bit_ports' treatment in case it's relevant for performance,
|
||||
// i.e. defer single-bit summands to be the last ones
|
||||
if (GetSize(port.in_a) == 1 && GetSize(port.in_b) == 0 && !port.is_signed && !port.do_subtract)
|
||||
bit_ports.append(port.in_a);
|
||||
else if (GetSize(port.in_b) == 0)
|
||||
worker.add(port.in_a, port.is_signed, port.do_subtract);
|
||||
else
|
||||
worker.add(port.in_a, port.in_b, port.is_signed, port.do_subtract);
|
||||
}
|
||||
|
||||
for (auto &bit : macc.bit_ports)
|
||||
for (auto bit : bit_ports)
|
||||
worker.add(bit, 0);
|
||||
|
||||
module->connect(cell->getPort(ID::Y), worker.synth());
|
||||
|
|
|
@ -201,18 +201,19 @@ static RTLIL::Cell* create_gold_module(RTLIL::Design *design, RTLIL::IdString ce
|
|||
this_port.do_subtract = xorshift32(2) == 1;
|
||||
macc.ports.push_back(this_port);
|
||||
}
|
||||
|
||||
wire = module->addWire(ID::B);
|
||||
wire->width = xorshift32(mulbits_a ? xorshift32(4)+1 : xorshift32(16)+1);
|
||||
wire->port_input = true;
|
||||
macc.bit_ports = wire;
|
||||
// Macc::to_cell sets the input ports
|
||||
macc.to_cell(cell);
|
||||
|
||||
wire = module->addWire(ID::Y);
|
||||
wire->width = width;
|
||||
wire->port_output = true;
|
||||
cell->setPort(ID::Y, wire);
|
||||
|
||||
macc.to_cell(cell);
|
||||
// override the B input (macc helpers always sets an empty vector)
|
||||
wire = module->addWire(ID::B);
|
||||
wire->width = xorshift32(mulbits_a ? xorshift32(4)+1 : xorshift32(16)+1);
|
||||
wire->port_input = true;
|
||||
cell->setPort(ID::B, wire);
|
||||
}
|
||||
|
||||
if (cell_type == ID($lut))
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
def generate(filename):
|
||||
with open(filename, "w") as f:
|
||||
f.write("// **AUTOGENERATED FILE** **DO NOT EDIT**\n")
|
||||
f.write(f"// Generated by {sys.argv[0]} at {datetime.now(timezone.utc)}\n")
|
||||
f.write(f"// Generated by {sys.argv[0]}\n")
|
||||
|
||||
f.write("`timescale 1ns /10ps\n")
|
||||
for a_width in [1,2,4,9,18,36]:
|
||||
|
|
50
tests/alumacc/macc_b_port_compat.ys
Normal file
50
tests/alumacc/macc_b_port_compat.ys
Normal file
|
@ -0,0 +1,50 @@
|
|||
# We don't set the B port on $macc cells anymore,
|
||||
# test compatibility with older RTLIL files which can
|
||||
# have the B port populated
|
||||
|
||||
read_verilog <<EOF
|
||||
module gold(input signed [2:0] a1, input signed [2:0] b1,
|
||||
input [1:0] a2, input [3:0] b2, input c, input d, output signed [3:0] y);
|
||||
wire signed [3:0] ab1;
|
||||
assign ab1 = a1 * b1;
|
||||
assign y = ab1 + a2*b2 + c + d + 1;
|
||||
endmodule
|
||||
EOF
|
||||
prep
|
||||
|
||||
# test the model for $macc including the retired B parameter
|
||||
# matches the gold module
|
||||
read_rtlil <<EOF
|
||||
attribute \src "<<EOF:1.1-4.10"
|
||||
module \gate
|
||||
wire width 3 input 1 signed \a1
|
||||
wire width 2 input 3 \a2
|
||||
wire width 3 input 2 signed \b1
|
||||
wire width 4 input 4 \b2
|
||||
wire input 5 \c
|
||||
wire input 6 \d
|
||||
wire width 4 output 7 signed \y
|
||||
|
||||
cell $macc $1
|
||||
parameter \A_WIDTH 12
|
||||
parameter \B_WIDTH 3
|
||||
parameter \CONFIG 20'01010000011011010011
|
||||
parameter \CONFIG_WIDTH 20
|
||||
parameter \Y_WIDTH 4
|
||||
connect \A { \a2 \b2 \b1 \a1 }
|
||||
connect \B { \d \c 1'1 }
|
||||
connect \Y \y
|
||||
end
|
||||
end
|
||||
EOF
|
||||
|
||||
design -save gold_gate
|
||||
equiv_make gold gate equiv
|
||||
equiv_induct equiv
|
||||
equiv_status -assert equiv
|
||||
|
||||
design -load gold_gate
|
||||
maccmap gate
|
||||
equiv_make gold gate equiv
|
||||
equiv_induct equiv
|
||||
equiv_status -assert equiv
|
6
tests/alumacc/run-test.sh
Normal file
6
tests/alumacc/run-test.sh
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
for x in *.ys; do
|
||||
echo "Running $x.."
|
||||
../../yosys -ql ${x%.ys}.log $x
|
||||
done
|
38
tests/various/json_scopeinfo.ys
Normal file
38
tests/various/json_scopeinfo.ys
Normal file
|
@ -0,0 +1,38 @@
|
|||
read_verilog <<EOT
|
||||
module top(input in, output out);
|
||||
wire [1:0] w1, w2;
|
||||
f1_test u1 (.in(in), .out(w1[0]));
|
||||
f2_test u2 (.in(w1), .out(w2));
|
||||
f3_test u3 (.in(w2[0]), .out(out));
|
||||
endmodule
|
||||
|
||||
module f1_test(input in, output out);
|
||||
assign out = in;
|
||||
endmodule
|
||||
|
||||
module f2_test(input [1:0] in, output [1:0] out);
|
||||
assign out[0] = in[0];
|
||||
assign out[1] = in[1];
|
||||
endmodule
|
||||
|
||||
module f3_test(input in, output [1:0] out);
|
||||
assign out[0] = in;
|
||||
assign out[1] = in;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -top top
|
||||
flatten -scopename
|
||||
prep
|
||||
|
||||
write_json json_scopeinfo.out
|
||||
!grep -qF '$scopeinfo' json_scopeinfo.out
|
||||
|
||||
write_json -noscopeinfo json_scopeinfo.out
|
||||
!grep -qvF '$scopeinfo' json_scopeinfo.out
|
||||
|
||||
json -o json_scopeinfo.out
|
||||
!grep -qF '$scopeinfo' json_scopeinfo.out
|
||||
|
||||
json -noscopeinfo -o json_scopeinfo.out
|
||||
!grep -qvF '$scopeinfo' json_scopeinfo.out
|
Loading…
Reference in a new issue