mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 09:05:32 +00:00
commit
5abaa59080
29 changed files with 2537 additions and 79 deletions
|
@ -43,3 +43,4 @@ OBJS += passes/cmds/logger.o
|
|||
OBJS += passes/cmds/printattrs.o
|
||||
OBJS += passes/cmds/sta.o
|
||||
OBJS += passes/cmds/clean_zerowidth.o
|
||||
OBJS += passes/cmds/xprop.o
|
||||
|
|
1198
passes/cmds/xprop.cc
Normal file
1198
passes/cmds/xprop.cc
Normal file
File diff suppressed because it is too large
Load diff
|
@ -643,6 +643,148 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
goto next_cell;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor)))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||
|
||||
bool a_fully_const = (sig_a.is_fully_const() && (!keepdc || !sig_a.is_fully_undef()));
|
||||
bool b_fully_const = (sig_b.is_fully_const() && (!keepdc || !sig_b.is_fully_undef()));
|
||||
|
||||
if (a_fully_const != b_fully_const)
|
||||
{
|
||||
cover("opt.opt_expr.bitwise_logic_one_const");
|
||||
log_debug("Replacing %s cell `%s' in module `%s' having one fully constant input\n",
|
||||
log_id(cell->type), log_id(cell->name), log_id(module));
|
||||
RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
|
||||
|
||||
int width = GetSize(cell->getPort(ID::Y));
|
||||
|
||||
sig_a.extend_u0(width, cell->getParam(ID::A_SIGNED).as_bool());
|
||||
sig_b.extend_u0(width, cell->getParam(ID::B_SIGNED).as_bool());
|
||||
|
||||
if (!a_fully_const)
|
||||
std::swap(sig_a, sig_b);
|
||||
|
||||
RTLIL::SigSpec b_group_0, b_group_1, b_group_x;
|
||||
RTLIL::SigSpec y_group_0, y_group_1, y_group_x;
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
auto bit_a = sig_a[i].data;
|
||||
if (bit_a == State::S0) b_group_0.append(sig_b[i]), y_group_0.append(sig_y[i]);
|
||||
if (bit_a == State::S1) b_group_1.append(sig_b[i]), y_group_1.append(sig_y[i]);
|
||||
if (bit_a == State::Sx) b_group_x.append(sig_b[i]), y_group_x.append(sig_y[i]);
|
||||
}
|
||||
|
||||
if (cell->type == ID($xnor)) {
|
||||
std::swap(b_group_0, b_group_1);
|
||||
std::swap(y_group_0, y_group_1);
|
||||
}
|
||||
|
||||
RTLIL::SigSpec y_new_0, y_new_1, y_new_x;
|
||||
|
||||
if (cell->type == ID($and)) {
|
||||
if (!y_group_0.empty()) y_new_0 = Const(State::S0, GetSize(y_group_0));
|
||||
if (!y_group_1.empty()) y_new_1 = b_group_1;
|
||||
if (!y_group_x.empty()) {
|
||||
if (keepdc)
|
||||
y_new_x = module->And(NEW_ID, Const(State::Sx, GetSize(y_group_x)), b_group_x);
|
||||
else
|
||||
y_new_x = Const(State::S0, GetSize(y_group_x));
|
||||
}
|
||||
} else if (cell->type == ID($or)) {
|
||||
if (!y_group_0.empty()) y_new_0 = b_group_0;
|
||||
if (!y_group_1.empty()) y_new_1 = Const(State::S1, GetSize(y_group_1));
|
||||
if (!y_group_x.empty()) {
|
||||
if (keepdc)
|
||||
y_new_x = module->Or(NEW_ID, Const(State::Sx, GetSize(y_group_x)), b_group_x);
|
||||
else
|
||||
y_new_x = Const(State::S1, GetSize(y_group_x));
|
||||
}
|
||||
} else if (cell->type.in(ID($xor), ID($xnor))) {
|
||||
if (!y_group_0.empty()) y_new_0 = b_group_0;
|
||||
if (!y_group_1.empty()) y_new_1 = module->Not(NEW_ID, b_group_1);
|
||||
if (!y_group_x.empty()) {
|
||||
if (keepdc)
|
||||
y_new_x = module->Xor(NEW_ID, Const(State::Sx, GetSize(y_group_x)), b_group_x);
|
||||
else // This should be fine even with keepdc, but opt_expr_xor.ys wants to keep the xor
|
||||
y_new_x = Const(State::Sx, GetSize(y_group_x));
|
||||
}
|
||||
} else {
|
||||
log_abort();
|
||||
}
|
||||
|
||||
assign_map.add(y_group_0, y_new_0); module->connect(y_group_0, y_new_0);
|
||||
assign_map.add(y_group_1, y_new_1); module->connect(y_group_1, y_new_1);
|
||||
assign_map.add(y_group_x, y_new_x); module->connect(y_group_x, y_new_x);
|
||||
|
||||
module->remove(cell);
|
||||
did_something = true;
|
||||
goto next_cell;
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->type == ID($bwmux))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||
RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S));
|
||||
RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
|
||||
int width = GetSize(cell->getPort(ID::Y));
|
||||
|
||||
if (sig_s.is_fully_def())
|
||||
{
|
||||
RTLIL::SigSpec a_group_0, b_group_1;
|
||||
RTLIL::SigSpec y_group_0, y_group_1;
|
||||
for (int i = 0; i < width; i++) {
|
||||
if (sig_s[i].data == State::S1)
|
||||
y_group_1.append(sig_y[i]), b_group_1.append(sig_b[i]);
|
||||
else
|
||||
y_group_0.append(sig_y[i]), a_group_0.append(sig_a[i]);
|
||||
}
|
||||
|
||||
assign_map.add(y_group_0, a_group_0); module->connect(y_group_0, a_group_0);
|
||||
assign_map.add(y_group_1, b_group_1); module->connect(y_group_1, b_group_1);
|
||||
|
||||
module->remove(cell);
|
||||
did_something = true;
|
||||
goto next_cell;
|
||||
}
|
||||
else if (sig_a.is_fully_def() || sig_b.is_fully_def())
|
||||
{
|
||||
bool flip = !sig_a.is_fully_def();
|
||||
if (flip)
|
||||
std::swap(sig_a, sig_b);
|
||||
|
||||
RTLIL::SigSpec b_group_0, b_group_1;
|
||||
RTLIL::SigSpec s_group_0, s_group_1;
|
||||
RTLIL::SigSpec y_group_0, y_group_1;
|
||||
for (int i = 0; i < width; i++) {
|
||||
if (sig_a[i].data == State::S1)
|
||||
y_group_1.append(sig_y[i]), b_group_1.append(sig_b[i]), s_group_1.append(sig_s[i]);
|
||||
else
|
||||
y_group_0.append(sig_y[i]), b_group_0.append(sig_b[i]), s_group_0.append(sig_s[i]);
|
||||
}
|
||||
|
||||
RTLIL::SigSpec y_new_0, y_new_1;
|
||||
|
||||
if (flip) {
|
||||
if (!y_group_0.empty()) y_new_0 = module->And(NEW_ID, b_group_0, module->Not(NEW_ID, s_group_0));
|
||||
if (!y_group_1.empty()) y_new_1 = module->Or(NEW_ID, b_group_1, s_group_1);
|
||||
} else {
|
||||
if (!y_group_0.empty()) y_new_0 = module->And(NEW_ID, b_group_0, s_group_0);
|
||||
if (!y_group_1.empty()) y_new_1 = module->Or(NEW_ID, b_group_1, module->Not(NEW_ID, s_group_1));
|
||||
}
|
||||
|
||||
module->connect(y_group_0, y_new_0);
|
||||
module->connect(y_group_1, y_new_1);
|
||||
|
||||
module->remove(cell);
|
||||
did_something = true;
|
||||
goto next_cell;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_fine)
|
||||
{
|
||||
if (cell->type.in(ID($not), ID($pos), ID($and), ID($or), ID($xor), ID($xnor)))
|
||||
|
@ -905,7 +1047,7 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($shiftx), ID($shift))) {
|
||||
if (cell->type.in(ID($shiftx), ID($shift)) && (cell->type == ID($shiftx) || !cell->getParam(ID::A_SIGNED).as_bool())) {
|
||||
SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||
int width;
|
||||
bool trim_x = cell->type == ID($shiftx) || !keepdc;
|
||||
|
@ -1152,7 +1294,7 @@ skip_fine_alu:
|
|||
goto next_cell;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && assign_map(cell->getPort(ID::B)).is_fully_const())
|
||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && (keepdc ? assign_map(cell->getPort(ID::B)).is_fully_def() : assign_map(cell->getPort(ID::B)).is_fully_const()))
|
||||
{
|
||||
bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID::A_SIGNED).as_bool();
|
||||
int shift_bits = assign_map(cell->getPort(ID::B)).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID::B_SIGNED).as_bool());
|
||||
|
@ -1163,7 +1305,7 @@ skip_fine_alu:
|
|||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||
RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID::Y_WIDTH).as_int());
|
||||
|
||||
if (GetSize(sig_a) < GetSize(sig_y))
|
||||
if (cell->type != ID($shiftx) && GetSize(sig_a) < GetSize(sig_y))
|
||||
sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID::A_SIGNED).as_bool());
|
||||
|
||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||
|
@ -1446,6 +1588,31 @@ skip_identity:
|
|||
goto next_cell; \
|
||||
} \
|
||||
}
|
||||
#define FOLD_2ARG_SIMPLE_CELL(_t, B_ID) \
|
||||
if (cell->type == ID($##_t)) { \
|
||||
RTLIL::SigSpec a = cell->getPort(ID::A); \
|
||||
RTLIL::SigSpec b = cell->getPort(B_ID); \
|
||||
assign_map.apply(a), assign_map.apply(b); \
|
||||
if (a.is_fully_const() && b.is_fully_const()) { \
|
||||
RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const())); \
|
||||
cover("opt.opt_expr.const.$" #_t); \
|
||||
replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID::Y, y); \
|
||||
goto next_cell; \
|
||||
} \
|
||||
}
|
||||
#define FOLD_MUX_CELL(_t) \
|
||||
if (cell->type == ID($##_t)) { \
|
||||
RTLIL::SigSpec a = cell->getPort(ID::A); \
|
||||
RTLIL::SigSpec b = cell->getPort(ID::B); \
|
||||
RTLIL::SigSpec s = cell->getPort(ID::S); \
|
||||
assign_map.apply(a), assign_map.apply(b), assign_map.apply(s); \
|
||||
if (a.is_fully_const() && b.is_fully_const() && s.is_fully_const()) { \
|
||||
RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), s.as_const())); \
|
||||
cover("opt.opt_expr.const.$" #_t); \
|
||||
replace_cell(assign_map, module, cell, stringf("%s, %s, %s", log_signal(a), log_signal(b), log_signal(s)), ID::Y, y); \
|
||||
goto next_cell; \
|
||||
} \
|
||||
}
|
||||
|
||||
FOLD_1ARG_CELL(not)
|
||||
FOLD_2ARG_CELL(and)
|
||||
|
@ -1477,6 +1644,9 @@ skip_identity:
|
|||
FOLD_2ARG_CELL(gt)
|
||||
FOLD_2ARG_CELL(ge)
|
||||
|
||||
FOLD_2ARG_CELL(eqx)
|
||||
FOLD_2ARG_CELL(nex)
|
||||
|
||||
FOLD_2ARG_CELL(add)
|
||||
FOLD_2ARG_CELL(sub)
|
||||
FOLD_2ARG_CELL(mul)
|
||||
|
@ -1489,6 +1659,13 @@ skip_identity:
|
|||
FOLD_1ARG_CELL(pos)
|
||||
FOLD_1ARG_CELL(neg)
|
||||
|
||||
FOLD_MUX_CELL(mux);
|
||||
FOLD_MUX_CELL(pmux);
|
||||
FOLD_2ARG_SIMPLE_CELL(bmux, ID::S);
|
||||
FOLD_2ARG_SIMPLE_CELL(demux, ID::S);
|
||||
FOLD_2ARG_SIMPLE_CELL(bweqx, ID::B);
|
||||
FOLD_MUX_CELL(bwmux);
|
||||
|
||||
// be very conservative with optimizing $mux cells as we do not want to break mux trees
|
||||
if (cell->type == ID($mux)) {
|
||||
RTLIL::SigSpec input = assign_map(cell->getPort(ID::S));
|
||||
|
|
|
@ -532,12 +532,14 @@ struct FormalFfPass : public Pass {
|
|||
if ((int)bits.size() == ff.val_init.size()) {
|
||||
// This check is only to make the private names more helpful for debugging
|
||||
ff.is_anyinit = true;
|
||||
ff.is_fine = false;
|
||||
emit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
auto slice = ff.slice(bits);
|
||||
slice.is_anyinit = is_anyinit;
|
||||
slice.is_fine = false;
|
||||
slice.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
|
|||
bool flag_make_outputs = false;
|
||||
bool flag_make_outcmp = false;
|
||||
bool flag_make_assert = false;
|
||||
bool flag_make_cover = false;
|
||||
bool flag_flatten = false;
|
||||
bool flag_cross = false;
|
||||
|
||||
|
@ -54,6 +55,10 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
|
|||
flag_make_assert = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-make_cover") {
|
||||
flag_make_cover = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-flatten") {
|
||||
flag_flatten = true;
|
||||
continue;
|
||||
|
@ -237,6 +242,12 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
|
|||
miter_module->connect(RTLIL::SigSig(w_cmp, this_condition));
|
||||
}
|
||||
|
||||
if (flag_make_cover)
|
||||
{
|
||||
auto cover_condition = miter_module->Not(NEW_ID, this_condition);
|
||||
miter_module->addCover("\\cover_" + RTLIL::unescape_id(gold_wire->name), cover_condition, State::S1);
|
||||
}
|
||||
|
||||
all_conditions.append(this_condition);
|
||||
}
|
||||
}
|
||||
|
@ -402,6 +413,9 @@ struct MiterPass : public Pass {
|
|||
log(" -make_assert\n");
|
||||
log(" also create an 'assert' cell that checks if trigger is always low.\n");
|
||||
log("\n");
|
||||
log(" -make_cover\n");
|
||||
log(" also create a 'cover' cell for each gold/gate output pair.\n");
|
||||
log("\n");
|
||||
log(" -flatten\n");
|
||||
log(" call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
|
||||
log("\n");
|
||||
|
|
|
@ -509,7 +509,7 @@ struct SimInstance
|
|||
}
|
||||
}
|
||||
|
||||
bool update_ph2()
|
||||
bool update_ph2(bool gclk)
|
||||
{
|
||||
bool did_something = false;
|
||||
|
||||
|
@ -567,7 +567,8 @@ struct SimInstance
|
|||
}
|
||||
if (ff_data.has_gclk) {
|
||||
// $ff
|
||||
current_q = ff.past_d;
|
||||
if (gclk)
|
||||
current_q = ff.past_d;
|
||||
}
|
||||
if (set_state(ff_data.sig_q, current_q))
|
||||
did_something = true;
|
||||
|
@ -616,7 +617,7 @@ struct SimInstance
|
|||
}
|
||||
|
||||
for (auto it : children)
|
||||
if (it.second->update_ph2()) {
|
||||
if (it.second->update_ph2(gclk)) {
|
||||
dirty_children.insert(it.second);
|
||||
did_something = true;
|
||||
}
|
||||
|
@ -985,7 +986,7 @@ struct SimWorker : SimShared
|
|||
writer->write(use_signal);
|
||||
}
|
||||
|
||||
void update()
|
||||
void update(bool gclk)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
|
@ -997,7 +998,7 @@ struct SimWorker : SimShared
|
|||
if (debug)
|
||||
log("\n-- ph2 --\n");
|
||||
|
||||
if (!top->update_ph2())
|
||||
if (!top->update_ph2(gclk))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1047,7 +1048,7 @@ struct SimWorker : SimShared
|
|||
set_inports(clock, State::Sx);
|
||||
set_inports(clockn, State::Sx);
|
||||
|
||||
update();
|
||||
update(false);
|
||||
|
||||
register_output_step(0);
|
||||
|
||||
|
@ -1060,7 +1061,7 @@ struct SimWorker : SimShared
|
|||
set_inports(clock, State::S0);
|
||||
set_inports(clockn, State::S1);
|
||||
|
||||
update();
|
||||
update(true);
|
||||
register_output_step(10*cycle + 5);
|
||||
|
||||
if (debug)
|
||||
|
@ -1076,7 +1077,7 @@ struct SimWorker : SimShared
|
|||
set_inports(resetn, State::S1);
|
||||
}
|
||||
|
||||
update();
|
||||
update(true);
|
||||
register_output_step(10*cycle + 10);
|
||||
}
|
||||
|
||||
|
@ -1193,7 +1194,7 @@ struct SimWorker : SimShared
|
|||
initial = false;
|
||||
}
|
||||
if (did_something)
|
||||
update();
|
||||
update(true);
|
||||
register_output_step(time);
|
||||
|
||||
bool status = top->checkSignals();
|
||||
|
@ -1342,12 +1343,12 @@ struct SimWorker : SimShared
|
|||
set_inports(clock, State::S0);
|
||||
set_inports(clockn, State::S1);
|
||||
}
|
||||
update();
|
||||
update(true);
|
||||
register_output_step(10*cycle);
|
||||
if (!multiclock && cycle) {
|
||||
set_inports(clock, State::S0);
|
||||
set_inports(clockn, State::S1);
|
||||
update();
|
||||
update(true);
|
||||
register_output_step(10*cycle + 5);
|
||||
}
|
||||
cycle++;
|
||||
|
@ -1419,12 +1420,12 @@ struct SimWorker : SimShared
|
|||
log("Simulating cycle %d.\n", cycle);
|
||||
set_inports(clock, State::S1);
|
||||
set_inports(clockn, State::S0);
|
||||
update();
|
||||
update(true);
|
||||
register_output_step(10*cycle+0);
|
||||
if (!multiclock) {
|
||||
set_inports(clock, State::S0);
|
||||
set_inports(clockn, State::S1);
|
||||
update();
|
||||
update(true);
|
||||
register_output_step(10*cycle+5);
|
||||
}
|
||||
cycle++;
|
||||
|
|
|
@ -31,6 +31,7 @@ OBJS += passes/techmap/dffinit.o
|
|||
OBJS += passes/techmap/pmuxtree.o
|
||||
OBJS += passes/techmap/bmuxmap.o
|
||||
OBJS += passes/techmap/demuxmap.o
|
||||
OBJS += passes/techmap/bwmuxmap.o
|
||||
OBJS += passes/techmap/muxcover.o
|
||||
OBJS += passes/techmap/aigmap.o
|
||||
OBJS += passes/techmap/tribuf.o
|
||||
|
|
70
passes/techmap/bwmuxmap.cc
Normal file
70
passes/techmap/bwmuxmap.cc
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2022 Jannis Harder <jix@yosyshq.com> <me@jix.one>
|
||||
*
|
||||
* 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/yosys.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct BwmuxmapPass : public Pass {
|
||||
BwmuxmapPass() : Pass("bwmuxmap", "replace $bwmux cells with equivalent logic") {}
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" bwmxumap [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This pass replaces $bwmux cells with equivalent logic\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing BWMUXMAP pass.\n");
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
// if (args[argidx] == "-arg") {
|
||||
// continue;
|
||||
// }
|
||||
break;
|
||||
}
|
||||
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type != ID($bwmux))
|
||||
continue;
|
||||
auto &sig_y = cell->getPort(ID::Y);
|
||||
auto &sig_a = cell->getPort(ID::A);
|
||||
auto &sig_b = cell->getPort(ID::B);
|
||||
auto &sig_s = cell->getPort(ID::S);
|
||||
|
||||
auto not_s = module->Not(NEW_ID, sig_s);
|
||||
auto masked_b = module->And(NEW_ID, sig_s, sig_b);
|
||||
auto masked_a = module->And(NEW_ID, not_s, sig_a);
|
||||
module->addOr(NEW_ID, masked_a, masked_b, sig_y);
|
||||
|
||||
module->remove(cell);
|
||||
}
|
||||
}
|
||||
} BwmuxmapPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -58,28 +58,17 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
|
|||
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||
|
||||
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool());
|
||||
sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID::B_SIGNED).as_bool());
|
||||
|
||||
if (cell->type == ID($xnor))
|
||||
{
|
||||
RTLIL::SigSpec sig_t = module->addWire(NEW_ID, GetSize(sig_y));
|
||||
|
||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
||||
gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
|
||||
gate->setPort(ID::A, sig_t[i]);
|
||||
gate->setPort(ID::Y, sig_y[i]);
|
||||
}
|
||||
|
||||
sig_y = sig_t;
|
||||
if (cell->type != ID($bweqx)) {
|
||||
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool());
|
||||
sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID::B_SIGNED).as_bool());
|
||||
}
|
||||
|
||||
IdString gate_type;
|
||||
if (cell->type == ID($and)) gate_type = ID($_AND_);
|
||||
if (cell->type == ID($or)) gate_type = ID($_OR_);
|
||||
if (cell->type == ID($xor)) gate_type = ID($_XOR_);
|
||||
if (cell->type == ID($xnor)) gate_type = ID($_XOR_);
|
||||
if (cell->type == ID($and)) gate_type = ID($_AND_);
|
||||
if (cell->type == ID($or)) gate_type = ID($_OR_);
|
||||
if (cell->type == ID($xor)) gate_type = ID($_XOR_);
|
||||
if (cell->type == ID($xnor)) gate_type = ID($_XNOR_);
|
||||
if (cell->type == ID($bweqx)) gate_type = ID($_XNOR_);
|
||||
log_assert(!gate_type.empty());
|
||||
|
||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||
|
@ -284,6 +273,23 @@ void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
|
|||
}
|
||||
}
|
||||
|
||||
void simplemap_bwmux(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||
{
|
||||
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||
RTLIL::SigSpec sig_s = cell->getPort(ID::S);
|
||||
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||
|
||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
|
||||
gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
|
||||
gate->setPort(ID::A, sig_a[i]);
|
||||
gate->setPort(ID::B, sig_b[i]);
|
||||
gate->setPort(ID::S, sig_s[i]);
|
||||
gate->setPort(ID::Y, sig_y[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||
{
|
||||
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||
|
@ -409,6 +415,7 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>
|
|||
mappers[ID($or)] = simplemap_bitop;
|
||||
mappers[ID($xor)] = simplemap_bitop;
|
||||
mappers[ID($xnor)] = simplemap_bitop;
|
||||
mappers[ID($bweqx)] = simplemap_bitop;
|
||||
mappers[ID($reduce_and)] = simplemap_reduce;
|
||||
mappers[ID($reduce_or)] = simplemap_reduce;
|
||||
mappers[ID($reduce_xor)] = simplemap_reduce;
|
||||
|
@ -422,6 +429,7 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>
|
|||
mappers[ID($ne)] = simplemap_eqne;
|
||||
mappers[ID($nex)] = simplemap_eqne;
|
||||
mappers[ID($mux)] = simplemap_mux;
|
||||
mappers[ID($bwmux)] = simplemap_bwmux;
|
||||
mappers[ID($tribuf)] = simplemap_tribuf;
|
||||
mappers[ID($bmux)] = simplemap_bmux;
|
||||
mappers[ID($lut)] = simplemap_lut;
|
||||
|
|
|
@ -31,6 +31,7 @@ extern void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell);
|
|||
extern void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell);
|
||||
extern void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell);
|
||||
extern void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell);
|
||||
extern void simplemap_bwmux(RTLIL::Module *module, RTLIL::Cell *cell);
|
||||
extern void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell);
|
||||
extern void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell);
|
||||
extern void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue