mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'origin/clifford/pmgenstuff' into xc7mux
This commit is contained in:
commit
8829cba901
|
@ -533,6 +533,42 @@ struct WreducePass : public Pass {
|
||||||
module->connect(sig, Const(0, GetSize(sig)));
|
module->connect(sig, Const(0, GetSize(sig)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->type.in("$div", "$mod", "$pow"))
|
||||||
|
{
|
||||||
|
SigSpec A = c->getPort("\\A");
|
||||||
|
int original_a_width = GetSize(A);
|
||||||
|
if (c->getParam("\\A_SIGNED").as_bool()) {
|
||||||
|
while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0)
|
||||||
|
A.remove(GetSize(A)-1, 1);
|
||||||
|
} else {
|
||||||
|
while (GetSize(A) > 0 && A[GetSize(A)-1] == State::S0)
|
||||||
|
A.remove(GetSize(A)-1, 1);
|
||||||
|
}
|
||||||
|
if (original_a_width != GetSize(A)) {
|
||||||
|
log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n",
|
||||||
|
original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type));
|
||||||
|
c->setPort("\\A", A);
|
||||||
|
c->setParam("\\A_WIDTH", GetSize(A));
|
||||||
|
}
|
||||||
|
|
||||||
|
SigSpec B = c->getPort("\\B");
|
||||||
|
int original_b_width = GetSize(B);
|
||||||
|
if (c->getParam("\\B_SIGNED").as_bool()) {
|
||||||
|
while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0)
|
||||||
|
B.remove(GetSize(B)-1, 1);
|
||||||
|
} else {
|
||||||
|
while (GetSize(B) > 0 && B[GetSize(B)-1] == State::S0)
|
||||||
|
B.remove(GetSize(B)-1, 1);
|
||||||
|
}
|
||||||
|
if (original_b_width != GetSize(B)) {
|
||||||
|
log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n",
|
||||||
|
original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type));
|
||||||
|
c->setPort("\\B", B);
|
||||||
|
c->setParam("\\B_WIDTH", GetSize(B));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) {
|
if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) {
|
||||||
IdString memid = c->getParam("\\MEMID").decode_string();
|
IdString memid = c->getParam("\\MEMID").decode_string();
|
||||||
RTLIL::Memory *mem = module->memories.at(memid);
|
RTLIL::Memory *mem = module->memories.at(memid);
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
/ice40_dsp_pm.h
|
/ice40_dsp_pm.h
|
||||||
|
/peepopt_pm.h
|
||||||
|
|
|
@ -1,8 +1,23 @@
|
||||||
OBJS += passes/pmgen/ice40_dsp.o
|
OBJS += passes/pmgen/ice40_dsp.o
|
||||||
|
OBJS += passes/pmgen/peepopt.o
|
||||||
|
|
||||||
|
# --------------------------------------
|
||||||
|
|
||||||
passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
|
passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
|
||||||
EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
|
EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
|
||||||
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
|
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
|
||||||
|
|
||||||
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
|
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
|
||||||
$(P) mkdir -p passes/pmgen && python3 $^ $@
|
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_dsp $(filter-out $<,$^)
|
||||||
|
|
||||||
|
# --------------------------------------
|
||||||
|
|
||||||
|
passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
|
||||||
|
EXTRA_OBJS += passes/pmgen/peepopt_pm.h
|
||||||
|
.SECONDARY: passes/pmgen/peepopt_pm.h
|
||||||
|
|
||||||
|
PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul.pmg
|
||||||
|
PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg
|
||||||
|
|
||||||
|
passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
|
||||||
|
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^)
|
||||||
|
|
|
@ -19,47 +19,50 @@
|
||||||
|
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "passes/pmgen/ice40_dsp_pm.h"
|
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
#include "passes/pmgen/ice40_dsp_pm.h"
|
||||||
|
|
||||||
void create_ice40_dsp(ice40_dsp_pm &pm)
|
void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
{
|
{
|
||||||
|
auto &st = pm.st_ice40_dsp;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
log("\n");
|
log("\n");
|
||||||
log("ffA: %s\n", log_id(pm.st.ffA, "--"));
|
log("ffA: %s\n", log_id(st.ffA, "--"));
|
||||||
log("ffB: %s\n", log_id(pm.st.ffB, "--"));
|
log("ffB: %s\n", log_id(st.ffB, "--"));
|
||||||
log("mul: %s\n", log_id(pm.st.mul, "--"));
|
log("mul: %s\n", log_id(st.mul, "--"));
|
||||||
log("ffY: %s\n", log_id(pm.st.ffY, "--"));
|
log("ffY: %s\n", log_id(st.ffY, "--"));
|
||||||
log("addAB: %s\n", log_id(pm.st.addAB, "--"));
|
log("addAB: %s\n", log_id(st.addAB, "--"));
|
||||||
log("muxAB: %s\n", log_id(pm.st.muxAB, "--"));
|
log("muxAB: %s\n", log_id(st.muxAB, "--"));
|
||||||
log("ffS: %s\n", log_id(pm.st.ffS, "--"));
|
log("ffS: %s\n", log_id(st.ffS, "--"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(pm.st.mul));
|
log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));
|
||||||
|
|
||||||
if (GetSize(pm.st.sigA) > 16) {
|
if (GetSize(st.sigA) > 16) {
|
||||||
log(" input A (%s) is too large (%d > 16).\n", log_signal(pm.st.sigA), GetSize(pm.st.sigA));
|
log(" input A (%s) is too large (%d > 16).\n", log_signal(st.sigA), GetSize(st.sigA));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSize(pm.st.sigB) > 16) {
|
if (GetSize(st.sigB) > 16) {
|
||||||
log(" input B (%s) is too large (%d > 16).\n", log_signal(pm.st.sigB), GetSize(pm.st.sigB));
|
log(" input B (%s) is too large (%d > 16).\n", log_signal(st.sigB), GetSize(st.sigB));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSize(pm.st.sigS) > 32) {
|
if (GetSize(st.sigS) > 32) {
|
||||||
log(" accumulator (%s) is too large (%d > 32).\n", log_signal(pm.st.sigS), GetSize(pm.st.sigS));
|
log(" accumulator (%s) is too large (%d > 32).\n", log_signal(st.sigS), GetSize(st.sigS));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSize(pm.st.sigY) > 32) {
|
if (GetSize(st.sigY) > 32) {
|
||||||
log(" output (%s) is too large (%d > 32).\n", log_signal(pm.st.sigY), GetSize(pm.st.sigY));
|
log(" output (%s) is too large (%d > 32).\n", log_signal(st.sigY), GetSize(st.sigY));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mul_signed = pm.st.mul->getParam("\\A_SIGNED").as_bool();
|
bool mul_signed = st.mul->getParam("\\A_SIGNED").as_bool();
|
||||||
|
|
||||||
if (mul_signed) {
|
if (mul_signed) {
|
||||||
log(" inference of signed iCE40 DSP arithmetic is currently not supported.\n");
|
log(" inference of signed iCE40 DSP arithmetic is currently not supported.\n");
|
||||||
|
@ -69,21 +72,21 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
log(" replacing $mul with SB_MAC16 cell.\n");
|
log(" replacing $mul with SB_MAC16 cell.\n");
|
||||||
|
|
||||||
Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16");
|
Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16");
|
||||||
pm.module->swap_names(cell, pm.st.mul);
|
pm.module->swap_names(cell, st.mul);
|
||||||
|
|
||||||
// SB_MAC16 Input Interface
|
// SB_MAC16 Input Interface
|
||||||
|
|
||||||
SigSpec A = pm.st.sigA;
|
SigSpec A = st.sigA;
|
||||||
A.extend_u0(16, mul_signed);
|
A.extend_u0(16, mul_signed);
|
||||||
|
|
||||||
SigSpec B = pm.st.sigB;
|
SigSpec B = st.sigB;
|
||||||
B.extend_u0(16, mul_signed);
|
B.extend_u0(16, mul_signed);
|
||||||
|
|
||||||
SigSpec CD;
|
SigSpec CD;
|
||||||
if (pm.st.muxA)
|
if (st.muxA)
|
||||||
CD = pm.st.muxA->getPort("\\B");
|
CD = st.muxA->getPort("\\B");
|
||||||
if (pm.st.muxB)
|
if (st.muxB)
|
||||||
CD = pm.st.muxB->getPort("\\A");
|
CD = st.muxB->getPort("\\A");
|
||||||
CD.extend_u0(32, mul_signed);
|
CD.extend_u0(32, mul_signed);
|
||||||
|
|
||||||
cell->setPort("\\A", A);
|
cell->setPort("\\A", A);
|
||||||
|
@ -91,8 +94,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setPort("\\C", CD.extract(0, 16));
|
cell->setPort("\\C", CD.extract(0, 16));
|
||||||
cell->setPort("\\D", CD.extract(16, 16));
|
cell->setPort("\\D", CD.extract(16, 16));
|
||||||
|
|
||||||
cell->setParam("\\A_REG", pm.st.ffA ? State::S1 : State::S0);
|
cell->setParam("\\A_REG", st.ffA ? State::S1 : State::S0);
|
||||||
cell->setParam("\\B_REG", pm.st.ffB ? State::S1 : State::S0);
|
cell->setParam("\\B_REG", st.ffB ? State::S1 : State::S0);
|
||||||
|
|
||||||
cell->setPort("\\AHOLD", State::S0);
|
cell->setPort("\\AHOLD", State::S0);
|
||||||
cell->setPort("\\BHOLD", State::S0);
|
cell->setPort("\\BHOLD", State::S0);
|
||||||
|
@ -102,25 +105,25 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setPort("\\IRSTTOP", State::S0);
|
cell->setPort("\\IRSTTOP", State::S0);
|
||||||
cell->setPort("\\IRSTBOT", State::S0);
|
cell->setPort("\\IRSTBOT", State::S0);
|
||||||
|
|
||||||
if (pm.st.clock_vld)
|
if (st.clock_vld)
|
||||||
{
|
{
|
||||||
cell->setPort("\\CLK", pm.st.clock);
|
cell->setPort("\\CLK", st.clock);
|
||||||
cell->setPort("\\CE", State::S1);
|
cell->setPort("\\CE", State::S1);
|
||||||
cell->setParam("\\NEG_TRIGGER", pm.st.clock_pol ? State::S0 : State::S1);
|
cell->setParam("\\NEG_TRIGGER", st.clock_pol ? State::S0 : State::S1);
|
||||||
|
|
||||||
log(" clock: %s (%s)", log_signal(pm.st.clock), pm.st.clock_pol ? "posedge" : "negedge");
|
log(" clock: %s (%s)", log_signal(st.clock), st.clock_pol ? "posedge" : "negedge");
|
||||||
|
|
||||||
if (pm.st.ffA)
|
if (st.ffA)
|
||||||
log(" ffA:%s", log_id(pm.st.ffA));
|
log(" ffA:%s", log_id(st.ffA));
|
||||||
|
|
||||||
if (pm.st.ffB)
|
if (st.ffB)
|
||||||
log(" ffB:%s", log_id(pm.st.ffB));
|
log(" ffB:%s", log_id(st.ffB));
|
||||||
|
|
||||||
if (pm.st.ffY)
|
if (st.ffY)
|
||||||
log(" ffY:%s", log_id(pm.st.ffY));
|
log(" ffY:%s", log_id(st.ffY));
|
||||||
|
|
||||||
if (pm.st.ffS)
|
if (st.ffS)
|
||||||
log(" ffS:%s", log_id(pm.st.ffS));
|
log(" ffS:%s", log_id(st.ffS));
|
||||||
|
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
@ -144,16 +147,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
|
|
||||||
// SB_MAC16 Output Interface
|
// SB_MAC16 Output Interface
|
||||||
|
|
||||||
SigSpec O = pm.st.ffS ? pm.st.sigS : pm.st.sigY;
|
SigSpec O = st.ffS ? st.sigS : st.sigY;
|
||||||
if (GetSize(O) < 32)
|
if (GetSize(O) < 32)
|
||||||
O.append(pm.module->addWire(NEW_ID, 32-GetSize(O)));
|
O.append(pm.module->addWire(NEW_ID, 32-GetSize(O)));
|
||||||
|
|
||||||
cell->setPort("\\O", O);
|
cell->setPort("\\O", O);
|
||||||
|
|
||||||
if (pm.st.addAB) {
|
if (st.addAB) {
|
||||||
log(" accumulator %s (%s)\n", log_id(pm.st.addAB), log_id(pm.st.addAB->type));
|
log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
|
||||||
cell->setPort("\\ADDSUBTOP", pm.st.addAB->type == "$add" ? State::S0 : State::S1);
|
cell->setPort("\\ADDSUBTOP", st.addAB->type == "$add" ? State::S0 : State::S1);
|
||||||
cell->setPort("\\ADDSUBBOT", pm.st.addAB->type == "$add" ? State::S0 : State::S1);
|
cell->setPort("\\ADDSUBBOT", st.addAB->type == "$add" ? State::S0 : State::S1);
|
||||||
} else {
|
} else {
|
||||||
cell->setPort("\\ADDSUBTOP", State::S0);
|
cell->setPort("\\ADDSUBTOP", State::S0);
|
||||||
cell->setPort("\\ADDSUBBOT", State::S0);
|
cell->setPort("\\ADDSUBBOT", State::S0);
|
||||||
|
@ -166,10 +169,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setPort("\\OHOLDBOT", State::S0);
|
cell->setPort("\\OHOLDBOT", State::S0);
|
||||||
|
|
||||||
SigSpec acc_reset = State::S0;
|
SigSpec acc_reset = State::S0;
|
||||||
if (pm.st.muxA)
|
if (st.muxA)
|
||||||
acc_reset = pm.st.muxA->getPort("\\S");
|
acc_reset = st.muxA->getPort("\\S");
|
||||||
if (pm.st.muxB)
|
if (st.muxB)
|
||||||
acc_reset = pm.module->Not(NEW_ID, pm.st.muxB->getPort("\\S"));
|
acc_reset = pm.module->Not(NEW_ID, st.muxB->getPort("\\S"));
|
||||||
|
|
||||||
cell->setPort("\\OLOADTOP", acc_reset);
|
cell->setPort("\\OLOADTOP", acc_reset);
|
||||||
cell->setPort("\\OLOADBOT", acc_reset);
|
cell->setPort("\\OLOADBOT", acc_reset);
|
||||||
|
@ -179,17 +182,17 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setParam("\\C_REG", State::S0);
|
cell->setParam("\\C_REG", State::S0);
|
||||||
cell->setParam("\\D_REG", State::S0);
|
cell->setParam("\\D_REG", State::S0);
|
||||||
|
|
||||||
cell->setParam("\\TOP_8x8_MULT_REG", pm.st.ffY ? State::S1 : State::S0);
|
cell->setParam("\\TOP_8x8_MULT_REG", st.ffY ? State::S1 : State::S0);
|
||||||
cell->setParam("\\BOT_8x8_MULT_REG", pm.st.ffY ? State::S1 : State::S0);
|
cell->setParam("\\BOT_8x8_MULT_REG", st.ffY ? State::S1 : State::S0);
|
||||||
cell->setParam("\\PIPELINE_16x16_MULT_REG1", pm.st.ffY ? State::S1 : State::S0);
|
cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffY ? State::S1 : State::S0);
|
||||||
cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0);
|
cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0);
|
||||||
|
|
||||||
cell->setParam("\\TOPOUTPUT_SELECT", Const(pm.st.ffS ? 1 : 3, 2));
|
cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2));
|
||||||
cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2));
|
cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2));
|
||||||
cell->setParam("\\TOPADDSUB_UPPERINPUT", State::S0);
|
cell->setParam("\\TOPADDSUB_UPPERINPUT", State::S0);
|
||||||
cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2));
|
cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2));
|
||||||
|
|
||||||
cell->setParam("\\BOTOUTPUT_SELECT", Const(pm.st.ffS ? 1 : 3, 2));
|
cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2));
|
||||||
cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2));
|
cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2));
|
||||||
cell->setParam("\\BOTADDSUB_UPPERINPUT", State::S0);
|
cell->setParam("\\BOTADDSUB_UPPERINPUT", State::S0);
|
||||||
cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2));
|
cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2));
|
||||||
|
@ -198,9 +201,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setParam("\\A_SIGNED", mul_signed ? State::S1 : State::S0);
|
cell->setParam("\\A_SIGNED", mul_signed ? State::S1 : State::S0);
|
||||||
cell->setParam("\\B_SIGNED", mul_signed ? State::S1 : State::S0);
|
cell->setParam("\\B_SIGNED", mul_signed ? State::S1 : State::S0);
|
||||||
|
|
||||||
pm.autoremove(pm.st.mul);
|
pm.autoremove(st.mul);
|
||||||
pm.autoremove(pm.st.ffY);
|
pm.autoremove(st.ffY);
|
||||||
pm.autoremove(pm.st.ffS);
|
pm.autoremove(st.ffS);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Ice40DspPass : public Pass {
|
struct Ice40DspPass : public Pass {
|
||||||
|
@ -230,7 +233,7 @@ struct Ice40DspPass : public Pass {
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
for (auto module : design->selected_modules())
|
for (auto module : design->selected_modules())
|
||||||
ice40_dsp_pm(module, module->selected_cells()).run(create_ice40_dsp);
|
ice40_dsp_pm(module, module->selected_cells()).run_ice40_dsp(create_ice40_dsp);
|
||||||
}
|
}
|
||||||
} Ice40DspPass;
|
} Ice40DspPass;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
pattern ice40_dsp
|
||||||
|
|
||||||
state <SigBit> clock
|
state <SigBit> clock
|
||||||
state <bool> clock_pol clock_vld
|
state <bool> clock_pol clock_vld
|
||||||
state <SigSpec> sigA sigB sigY sigS
|
state <SigSpec> sigA sigB sigY sigS
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
bool did_something;
|
||||||
|
|
||||||
|
#include "passes/pmgen/peepopt_pm.h"
|
||||||
|
|
||||||
|
struct PeepoptPass : public Pass {
|
||||||
|
PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" peepopt [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("This pass applies a collection of peephole optimizers to the current design.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing PEEOPOPT pass (run peephole optimizers).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
// if (args[argidx] == "-singleton") {
|
||||||
|
// singleton_mode = true;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules()) {
|
||||||
|
did_something = true;
|
||||||
|
while (did_something) {
|
||||||
|
did_something = false;
|
||||||
|
peepopt_pm pm(module, module->selected_cells());
|
||||||
|
pm.run_shiftmul();
|
||||||
|
pm.run_muldiv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} PeepoptPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,36 @@
|
||||||
|
pattern muldiv
|
||||||
|
|
||||||
|
state <SigSpec> t x y
|
||||||
|
|
||||||
|
match mul
|
||||||
|
select mul->type == $mul
|
||||||
|
select GetSize(port(mul, \A)) + GetSize(port(mul, \B)) <= GetSize(port(mul, \Y))
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code t x y
|
||||||
|
t = port(mul, \Y);
|
||||||
|
x = port(mul, \A);
|
||||||
|
y = port(mul, \B);
|
||||||
|
branch;
|
||||||
|
std::swap(x, y);
|
||||||
|
endcode
|
||||||
|
|
||||||
|
match div
|
||||||
|
select div->type.in($div)
|
||||||
|
index <SigSpec> port(div, \A) === t
|
||||||
|
index <SigSpec> port(div, \B) === x
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
SigSpec div_y = port(div, \Y);
|
||||||
|
SigSpec val_y = y;
|
||||||
|
|
||||||
|
if (GetSize(div_y) != GetSize(val_y))
|
||||||
|
val_y.extend_u0(GetSize(div_y), param(div, \A_SIGNED).as_bool());
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
|
log("muldiv pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div));
|
||||||
|
module->connect(div_y, val_y);
|
||||||
|
autoremove(div);
|
||||||
|
reject;
|
||||||
|
endcode
|
|
@ -0,0 +1,83 @@
|
||||||
|
pattern shiftmul
|
||||||
|
|
||||||
|
state <SigSpec> shamt
|
||||||
|
|
||||||
|
match shift
|
||||||
|
select shift->type.in($shift, $shiftx, $shr)
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code shamt
|
||||||
|
shamt = port(shift, \B);
|
||||||
|
if (shamt[GetSize(shamt)-1] == State::S0) {
|
||||||
|
do {
|
||||||
|
shamt.remove(GetSize(shamt)-1);
|
||||||
|
} while (shamt[GetSize(shamt)-1] == State::S0);
|
||||||
|
} else
|
||||||
|
if (shift->type.in($shift, $shiftx) && param(shift, \B_SIGNED).as_bool()) {
|
||||||
|
reject;
|
||||||
|
}
|
||||||
|
if (GetSize(shamt) > 20)
|
||||||
|
reject;
|
||||||
|
endcode
|
||||||
|
|
||||||
|
match mul
|
||||||
|
select mul->type.in($mul)
|
||||||
|
select port(mul, \A).is_fully_const() || port(mul, \B).is_fully_const()
|
||||||
|
index <SigSpec> port(mul, \Y) === shamt
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
IdString const_factor_port = port(mul, \A).is_fully_const() ? \A : \B;
|
||||||
|
IdString const_factor_signed = const_factor_port == \A ? \A_SIGNED : \B_SIGNED;
|
||||||
|
Const const_factor_cnst = port(mul, const_factor_port).as_const();
|
||||||
|
int const_factor = const_factor_cnst.as_int();
|
||||||
|
|
||||||
|
if (GetSize(const_factor_cnst) == 0)
|
||||||
|
reject;
|
||||||
|
|
||||||
|
if (const_factor_cnst.bits[GetSize(const_factor_cnst)-1] != State::S0 &&
|
||||||
|
param(mul, const_factor_signed).as_bool())
|
||||||
|
reject;
|
||||||
|
|
||||||
|
if (GetSize(const_factor_cnst) > 20)
|
||||||
|
reject;
|
||||||
|
|
||||||
|
if (GetSize(port(shift, \Y)) > const_factor)
|
||||||
|
reject;
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
|
log("shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul));
|
||||||
|
|
||||||
|
int new_const_factor_log2 = ceil_log2(const_factor);
|
||||||
|
int new_const_factor = 1 << new_const_factor_log2;
|
||||||
|
|
||||||
|
SigSpec padding(State::Sx, new_const_factor-const_factor);
|
||||||
|
SigSpec old_a = port(shift, \A), new_a;
|
||||||
|
int trunc = 0;
|
||||||
|
|
||||||
|
if (GetSize(old_a) % const_factor != 0) {
|
||||||
|
trunc = const_factor - GetSize(old_a) % const_factor;
|
||||||
|
old_a.append(SigSpec(State::Sx, trunc));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i*const_factor < GetSize(old_a); i++) {
|
||||||
|
SigSpec slice = old_a.extract(i*const_factor, const_factor);
|
||||||
|
new_a.append(slice);
|
||||||
|
new_a.append(padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trunc > 0)
|
||||||
|
new_a.remove(GetSize(new_a)-trunc, trunc);
|
||||||
|
|
||||||
|
SigSpec new_b = {port(mul, const_factor_port == \A ? \B : \A), SigSpec(State::S0, new_const_factor_log2)};
|
||||||
|
if (param(shift, \B_SIGNED).as_bool())
|
||||||
|
new_b.append(State::S0);
|
||||||
|
|
||||||
|
shift->setPort(\A, new_a);
|
||||||
|
shift->setParam(\A_WIDTH, GetSize(new_a));
|
||||||
|
shift->setPort(\B, new_b);
|
||||||
|
shift->setParam(\B_WIDTH, GetSize(new_b));
|
||||||
|
|
||||||
|
blacklist(shift);
|
||||||
|
reject;
|
||||||
|
endcode
|
|
@ -3,15 +3,42 @@
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import pprint
|
import pprint
|
||||||
|
import getopt
|
||||||
|
|
||||||
pp = pprint.PrettyPrinter(indent=4)
|
pp = pprint.PrettyPrinter(indent=4)
|
||||||
|
|
||||||
pmgfile = sys.argv[1]
|
prefix = None
|
||||||
assert pmgfile.endswith(".pmg")
|
pmgfiles = list()
|
||||||
prefix = pmgfile[0:-4]
|
outfile = None
|
||||||
prefix = prefix.split('/')[-1]
|
debug = False
|
||||||
outfile = sys.argv[2]
|
genhdr = False
|
||||||
|
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], "p:o:dg")
|
||||||
|
|
||||||
|
for o, a in opts:
|
||||||
|
if o == "-p":
|
||||||
|
prefix = a
|
||||||
|
elif o == "-o":
|
||||||
|
outfile = a
|
||||||
|
elif o == "-d":
|
||||||
|
debug = True
|
||||||
|
elif o == "-g":
|
||||||
|
genhdr = True
|
||||||
|
|
||||||
|
if outfile is None:
|
||||||
|
outfile = "/dev/stdout"
|
||||||
|
|
||||||
|
for a in args:
|
||||||
|
assert a.endswith(".pmg")
|
||||||
|
if prefix is None and len(args) == 1:
|
||||||
|
prefix = a[0:-4]
|
||||||
|
prefix = prefix.split('/')[-1]
|
||||||
|
pmgfiles.append(a)
|
||||||
|
|
||||||
|
assert prefix is not None
|
||||||
|
|
||||||
|
current_pattern = None
|
||||||
|
patterns = dict()
|
||||||
state_types = dict()
|
state_types = dict()
|
||||||
udata_types = dict()
|
udata_types = dict()
|
||||||
blocks = list()
|
blocks = list()
|
||||||
|
@ -77,7 +104,8 @@ def rewrite_cpp(s):
|
||||||
|
|
||||||
return "".join(t)
|
return "".join(t)
|
||||||
|
|
||||||
with open(pmgfile, "r") as f:
|
def process_pmgfile(f):
|
||||||
|
global current_pattern
|
||||||
while True:
|
while True:
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
if line == "": break
|
if line == "": break
|
||||||
|
@ -87,14 +115,31 @@ with open(pmgfile, "r") as f:
|
||||||
if len(cmd) == 0 or cmd[0].startswith("//"): continue
|
if len(cmd) == 0 or cmd[0].startswith("//"): continue
|
||||||
cmd = cmd[0]
|
cmd = cmd[0]
|
||||||
|
|
||||||
|
if cmd == "pattern":
|
||||||
|
if current_pattern is not None:
|
||||||
|
block = dict()
|
||||||
|
block["type"] = "final"
|
||||||
|
block["pattern"] = current_pattern
|
||||||
|
blocks.append(block)
|
||||||
|
line = line.split()
|
||||||
|
assert len(line) == 2
|
||||||
|
assert line[1] not in patterns
|
||||||
|
current_pattern = line[1]
|
||||||
|
patterns[current_pattern] = len(blocks)
|
||||||
|
state_types[current_pattern] = dict()
|
||||||
|
udata_types[current_pattern] = dict()
|
||||||
|
continue
|
||||||
|
|
||||||
|
assert current_pattern is not None
|
||||||
|
|
||||||
if cmd == "state":
|
if cmd == "state":
|
||||||
m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line)
|
m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line)
|
||||||
assert m
|
assert m
|
||||||
type_str = m.group(1)
|
type_str = m.group(1)
|
||||||
states_str = m.group(2)
|
states_str = m.group(2)
|
||||||
for s in re.split(r"\s+", states_str):
|
for s in re.split(r"\s+", states_str):
|
||||||
assert s not in state_types
|
assert s not in state_types[current_pattern]
|
||||||
state_types[s] = type_str
|
state_types[current_pattern][s] = type_str
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if cmd == "udata":
|
if cmd == "udata":
|
||||||
|
@ -103,19 +148,20 @@ with open(pmgfile, "r") as f:
|
||||||
type_str = m.group(1)
|
type_str = m.group(1)
|
||||||
udatas_str = m.group(2)
|
udatas_str = m.group(2)
|
||||||
for s in re.split(r"\s+", udatas_str):
|
for s in re.split(r"\s+", udatas_str):
|
||||||
assert s not in udata_types
|
assert s not in udata_types[current_pattern]
|
||||||
udata_types[s] = type_str
|
udata_types[current_pattern][s] = type_str
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if cmd == "match":
|
if cmd == "match":
|
||||||
block = dict()
|
block = dict()
|
||||||
block["type"] = "match"
|
block["type"] = "match"
|
||||||
|
block["pattern"] = current_pattern
|
||||||
|
|
||||||
line = line.split()
|
line = line.split()
|
||||||
assert len(line) == 2
|
assert len(line) == 2
|
||||||
assert line[1] not in state_types
|
assert line[1] not in state_types[current_pattern]
|
||||||
block["cell"] = line[1]
|
block["cell"] = line[1]
|
||||||
state_types[line[1]] = "Cell*";
|
state_types[current_pattern][line[1]] = "Cell*";
|
||||||
|
|
||||||
block["if"] = list()
|
block["if"] = list()
|
||||||
block["select"] = list()
|
block["select"] = list()
|
||||||
|
@ -158,15 +204,18 @@ with open(pmgfile, "r") as f:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
|
continue
|
||||||
|
|
||||||
if cmd == "code":
|
if cmd == "code":
|
||||||
block = dict()
|
block = dict()
|
||||||
block["type"] = "code"
|
block["type"] = "code"
|
||||||
|
block["pattern"] = current_pattern
|
||||||
|
|
||||||
block["code"] = list()
|
block["code"] = list()
|
||||||
block["states"] = set()
|
block["states"] = set()
|
||||||
|
|
||||||
for s in line.split()[1:]:
|
for s in line.split()[1:]:
|
||||||
assert s in state_types
|
assert s in state_types[current_pattern]
|
||||||
block["states"].add(s)
|
block["states"].add(s)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
@ -179,17 +228,36 @@ with open(pmgfile, "r") as f:
|
||||||
block["code"].append(rewrite_cpp(l.rstrip()))
|
block["code"].append(rewrite_cpp(l.rstrip()))
|
||||||
|
|
||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
|
continue
|
||||||
|
|
||||||
|
assert False
|
||||||
|
|
||||||
|
for fn in pmgfiles:
|
||||||
|
with open(fn, "r") as f:
|
||||||
|
process_pmgfile(f)
|
||||||
|
|
||||||
|
if current_pattern is not None:
|
||||||
|
block = dict()
|
||||||
|
block["type"] = "final"
|
||||||
|
block["pattern"] = current_pattern
|
||||||
|
blocks.append(block)
|
||||||
|
|
||||||
|
current_pattern = None
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
pp.pprint(blocks)
|
||||||
|
|
||||||
with open(outfile, "w") as f:
|
with open(outfile, "w") as f:
|
||||||
print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f)
|
for fn in pmgfiles:
|
||||||
|
print("// Generated by pmgen.py from {}".format(fn), file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print("#include \"kernel/yosys.h\"", file=f)
|
if genhdr:
|
||||||
print("#include \"kernel/sigtools.h\"", file=f)
|
print("#include \"kernel/yosys.h\"", file=f)
|
||||||
print("", file=f)
|
print("#include \"kernel/sigtools.h\"", file=f)
|
||||||
|
print("", file=f)
|
||||||
print("YOSYS_NAMESPACE_BEGIN", file=f)
|
print("YOSYS_NAMESPACE_BEGIN", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print("struct {}_pm {{".format(prefix), file=f)
|
print("struct {}_pm {{".format(prefix), file=f)
|
||||||
print(" Module *module;", file=f)
|
print(" Module *module;", file=f)
|
||||||
|
@ -212,17 +280,19 @@ with open(outfile, "w") as f:
|
||||||
print(" int rollback;", file=f)
|
print(" int rollback;", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print(" struct state_t {", file=f)
|
for current_pattern in sorted(patterns.keys()):
|
||||||
for s, t in sorted(state_types.items()):
|
print(" struct state_{}_t {{".format(current_pattern), file=f)
|
||||||
print(" {} {};".format(t, s), file=f)
|
for s, t in sorted(state_types[current_pattern].items()):
|
||||||
print(" } st;", file=f)
|
print(" {} {};".format(t, s), file=f)
|
||||||
print("", file=f)
|
print(" }} st_{};".format(current_pattern), file=f)
|
||||||
|
print("", file=f)
|
||||||
|
|
||||||
print(" struct udata_t {", file=f)
|
print(" struct udata_{}_t {{".format(current_pattern), file=f)
|
||||||
for s, t in sorted(udata_types.items()):
|
for s, t in sorted(udata_types[current_pattern].items()):
|
||||||
print(" {} {};".format(t, s), file=f)
|
print(" {} {};".format(t, s), file=f)
|
||||||
print(" } ud;", file=f)
|
print(" }} ud_{};".format(current_pattern), file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
current_pattern = None
|
||||||
|
|
||||||
for v, n in sorted(ids.items()):
|
for v, n in sorted(ids.items()):
|
||||||
if n[0] == "\\":
|
if n[0] == "\\":
|
||||||
|
@ -258,20 +328,24 @@ with open(outfile, "w") as f:
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print(" void check_blacklist() {", file=f)
|
for current_pattern in sorted(patterns.keys()):
|
||||||
print(" if (!blacklist_dirty)", file=f)
|
print(" void check_blacklist_{}() {{".format(current_pattern), file=f)
|
||||||
print(" return;", file=f)
|
print(" if (!blacklist_dirty)", file=f)
|
||||||
print(" blacklist_dirty = false;", file=f)
|
print(" return;", file=f)
|
||||||
for index in range(len(blocks)):
|
print(" blacklist_dirty = false;", file=f)
|
||||||
block = blocks[index]
|
for index in range(len(blocks)):
|
||||||
if block["type"] == "match":
|
block = blocks[index]
|
||||||
print(" if (st.{} != nullptr && blacklist_cells.count(st.{})) {{".format(block["cell"], block["cell"]), file=f)
|
if block["pattern"] != current_pattern:
|
||||||
print(" rollback = {};".format(index+1), file=f)
|
continue
|
||||||
print(" return;", file=f)
|
if block["type"] == "match":
|
||||||
print(" }", file=f)
|
print(" if (st_{}.{} != nullptr && blacklist_cells.count(st_{}.{})) {{".format(current_pattern, block["cell"], current_pattern, block["cell"]), file=f)
|
||||||
print(" rollback = 0;", file=f)
|
print(" rollback = {};".format(index+1), file=f)
|
||||||
print(" }", file=f)
|
print(" return;", file=f)
|
||||||
print("", file=f)
|
print(" }", file=f)
|
||||||
|
print(" rollback = 0;", file=f)
|
||||||
|
print(" }", file=f)
|
||||||
|
print("", file=f)
|
||||||
|
current_pattern = None
|
||||||
|
|
||||||
print(" SigSpec port(Cell *cell, IdString portname) {", file=f)
|
print(" SigSpec port(Cell *cell, IdString portname) {", file=f)
|
||||||
print(" return sigmap(cell->getPort(portname));", file=f)
|
print(" return sigmap(cell->getPort(portname));", file=f)
|
||||||
|
@ -294,11 +368,13 @@ with open(outfile, "w") as f:
|
||||||
|
|
||||||
print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f)
|
print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f)
|
||||||
print(" module(module), sigmap(module) {", file=f)
|
print(" module(module), sigmap(module) {", file=f)
|
||||||
for s, t in sorted(udata_types.items()):
|
for current_pattern in sorted(patterns.keys()):
|
||||||
if t.endswith("*"):
|
for s, t in sorted(udata_types[current_pattern].items()):
|
||||||
print(" ud.{} = nullptr;".format(s), file=f)
|
if t.endswith("*"):
|
||||||
else:
|
print(" ud_{}.{} = nullptr;".format(current_pattern,s), file=f)
|
||||||
print(" ud.{} = {}();".format(s, t), file=f)
|
else:
|
||||||
|
print(" ud_{}.{} = {}();".format(current_pattern, s, t), file=f)
|
||||||
|
current_pattern = None
|
||||||
print(" for (auto cell : module->cells()) {", file=f)
|
print(" for (auto cell : module->cells()) {", file=f)
|
||||||
print(" for (auto &conn : cell->connections())", file=f)
|
print(" for (auto &conn : cell->connections())", file=f)
|
||||||
print(" add_siguser(conn.second, cell);", file=f)
|
print(" add_siguser(conn.second, cell);", file=f)
|
||||||
|
@ -328,34 +404,52 @@ with open(outfile, "w") as f:
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print(" void run(std::function<void()> on_accept_f) {", file=f)
|
for current_pattern in sorted(patterns.keys()):
|
||||||
print(" on_accept = on_accept_f;", file=f)
|
print(" void run_{}(std::function<void()> on_accept_f) {{".format(current_pattern), file=f)
|
||||||
print(" rollback = 0;", file=f)
|
print(" on_accept = on_accept_f;", file=f)
|
||||||
print(" blacklist_dirty = false;", file=f)
|
print(" rollback = 0;", file=f)
|
||||||
for s, t in sorted(state_types.items()):
|
print(" blacklist_dirty = false;", file=f)
|
||||||
if t.endswith("*"):
|
for s, t in sorted(state_types[current_pattern].items()):
|
||||||
print(" st.{} = nullptr;".format(s), file=f)
|
if t.endswith("*"):
|
||||||
else:
|
print(" st_{}.{} = nullptr;".format(current_pattern, s), file=f)
|
||||||
print(" st.{} = {}();".format(s, t), file=f)
|
else:
|
||||||
print(" block_0();", file=f)
|
print(" st_{}.{} = {}();".format(current_pattern, s, t), file=f)
|
||||||
print(" }", file=f)
|
print(" block_{}();".format(patterns[current_pattern]), file=f)
|
||||||
print("", file=f)
|
print(" }", file=f)
|
||||||
|
print("", file=f)
|
||||||
print(" void run(std::function<void({}_pm&)> on_accept_f) {{".format(prefix), file=f)
|
print(" void run_{}(std::function<void({}_pm&)> on_accept_f) {{".format(current_pattern, prefix), file=f)
|
||||||
print(" run([&](){on_accept_f(*this);});", file=f)
|
print(" run_{}([&](){{on_accept_f(*this);}});".format(current_pattern), file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
print(" void run_{}(std::function<void(state_{}_t&)> on_accept_f) {{".format(current_pattern, current_pattern), file=f)
|
||||||
|
print(" run_{}([&](){{on_accept_f(st_{});}});".format(current_pattern, current_pattern), file=f)
|
||||||
|
print(" }", file=f)
|
||||||
|
print("", file=f)
|
||||||
|
print(" void run_{}() {{".format(current_pattern), file=f)
|
||||||
|
print(" run_{}([](){{}});".format(current_pattern, current_pattern), file=f)
|
||||||
|
print(" }", file=f)
|
||||||
|
print("", file=f)
|
||||||
|
current_pattern = None
|
||||||
|
|
||||||
for index in range(len(blocks)):
|
for index in range(len(blocks)):
|
||||||
block = blocks[index]
|
block = blocks[index]
|
||||||
|
|
||||||
print(" void block_{}() {{".format(index), file=f)
|
print(" void block_{}() {{".format(index), file=f)
|
||||||
|
current_pattern = block["pattern"]
|
||||||
|
|
||||||
|
if block["type"] == "final":
|
||||||
|
print(" on_accept();", file=f)
|
||||||
|
print(" check_blacklist_{}();".format(current_pattern), file=f)
|
||||||
|
print(" }", file=f)
|
||||||
|
if index+1 != len(blocks):
|
||||||
|
print("", file=f)
|
||||||
|
continue
|
||||||
|
|
||||||
const_st = set()
|
const_st = set()
|
||||||
nonconst_st = set()
|
nonconst_st = set()
|
||||||
restore_st = set()
|
restore_st = set()
|
||||||
|
|
||||||
for i in range(index):
|
for i in range(patterns[current_pattern], index):
|
||||||
if blocks[i]["type"] == "code":
|
if blocks[i]["type"] == "code":
|
||||||
for s in blocks[i]["states"]:
|
for s in blocks[i]["states"]:
|
||||||
const_st.add(s)
|
const_st.add(s)
|
||||||
|
@ -378,27 +472,27 @@ with open(outfile, "w") as f:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
for s in sorted(const_st):
|
for s in sorted(const_st):
|
||||||
t = state_types[s]
|
t = state_types[current_pattern][s]
|
||||||
if t.endswith("*"):
|
if t.endswith("*"):
|
||||||
print(" {} const &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f)
|
print(" {} const &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)
|
||||||
else:
|
else:
|
||||||
print(" const {} &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f)
|
print(" const {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)
|
||||||
|
|
||||||
for s in sorted(nonconst_st):
|
for s in sorted(nonconst_st):
|
||||||
t = state_types[s]
|
t = state_types[current_pattern][s]
|
||||||
print(" {} &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f)
|
print(" {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)
|
||||||
|
|
||||||
if len(restore_st):
|
if len(restore_st):
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
for s in sorted(restore_st):
|
for s in sorted(restore_st):
|
||||||
t = state_types[s]
|
t = state_types[current_pattern][s]
|
||||||
print(" {} backup_{} = {};".format(t, s, s), file=f)
|
print(" {} backup_{} = {};".format(t, s, s), file=f)
|
||||||
|
|
||||||
if block["type"] == "code":
|
if block["type"] == "code":
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" do {", file=f)
|
print(" do {", file=f)
|
||||||
print("#define reject do { check_blacklist(); goto rollback_label; } while(0)", file=f)
|
print("#define reject do {{ check_blacklist_{}(); goto rollback_label; }} while(0)".format(current_pattern), file=f)
|
||||||
print("#define accept do { on_accept(); check_blacklist(); if (rollback) goto rollback_label; } while(0)", file=f)
|
print("#define accept do {{ on_accept(); check_blacklist_{}(); if (rollback) goto rollback_label; }} while(0)".format(current_pattern), file=f)
|
||||||
print("#define branch do {{ block_{}(); if (rollback) goto rollback_label; }} while(0)".format(index+1), file=f)
|
print("#define branch do {{ block_{}(); if (rollback) goto rollback_label; }} while(0)".format(index+1), file=f)
|
||||||
|
|
||||||
for line in block["code"]:
|
for line in block["code"]:
|
||||||
|
@ -417,11 +511,11 @@ with open(outfile, "w") as f:
|
||||||
if len(restore_st) or len(nonconst_st):
|
if len(restore_st) or len(nonconst_st):
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
for s in sorted(restore_st):
|
for s in sorted(restore_st):
|
||||||
t = state_types[s]
|
t = state_types[current_pattern][s]
|
||||||
print(" {} = backup_{};".format(s, s), file=f)
|
print(" {} = backup_{};".format(s, s), file=f)
|
||||||
for s in sorted(nonconst_st):
|
for s in sorted(nonconst_st):
|
||||||
if s not in restore_st:
|
if s not in restore_st:
|
||||||
t = state_types[s]
|
t = state_types[current_pattern][s]
|
||||||
if t.endswith("*"):
|
if t.endswith("*"):
|
||||||
print(" {} = nullptr;".format(s), file=f)
|
print(" {} = nullptr;".format(s), file=f)
|
||||||
else:
|
else:
|
||||||
|
@ -470,17 +564,12 @@ with open(outfile, "w") as f:
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
current_pattern = None
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print(" void block_{}() {{".format(len(blocks)), file=f)
|
|
||||||
print(" on_accept();", file=f)
|
|
||||||
print(" check_blacklist();", file=f)
|
|
||||||
print(" }", file=f)
|
|
||||||
print("};", file=f)
|
print("};", file=f)
|
||||||
|
|
||||||
print("", file=f)
|
if genhdr:
|
||||||
print("YOSYS_NAMESPACE_END", file=f)
|
print("", file=f)
|
||||||
|
print("YOSYS_NAMESPACE_END", file=f)
|
||||||
# pp.pprint(blocks)
|
|
||||||
|
|
|
@ -209,6 +209,8 @@ struct SynthPass : public ScriptPass
|
||||||
run("check");
|
run("check");
|
||||||
run("opt");
|
run("opt");
|
||||||
run("wreduce");
|
run("wreduce");
|
||||||
|
run("peepopt");
|
||||||
|
run("opt_clean");
|
||||||
if (help_mode)
|
if (help_mode)
|
||||||
run("techmap -map +/cmp2lut.v", " (if -lut)");
|
run("techmap -map +/cmp2lut.v", " (if -lut)");
|
||||||
else
|
else
|
||||||
|
|
|
@ -261,6 +261,8 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
run("check");
|
run("check");
|
||||||
run("opt");
|
run("opt");
|
||||||
run("wreduce");
|
run("wreduce");
|
||||||
|
run("peepopt");
|
||||||
|
run("opt_clean");
|
||||||
run("share");
|
run("share");
|
||||||
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
|
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
|
||||||
run("opt_expr");
|
run("opt_expr");
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
module peepopt_shiftmul_0 #(parameter N=3, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output [W-1:0] o);
|
||||||
|
assign o = i[s*W+:W];
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module peepopt_muldiv_0(input [1:0] i, output [1:0] o);
|
||||||
|
wire [3:0] t;
|
||||||
|
assign t = i * 3;
|
||||||
|
assign o = t / 3;
|
||||||
|
endmodule
|
Loading…
Reference in New Issue