mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #1289 from mmicko/anlogic_fixes
Anlogic fixes and optimization
This commit is contained in:
commit
2c8c8b3c74
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
OBJS += techlibs/anlogic/synth_anlogic.o
|
OBJS += techlibs/anlogic/synth_anlogic.o
|
||||||
OBJS += techlibs/anlogic/anlogic_eqn.o
|
OBJS += techlibs/anlogic/anlogic_eqn.o
|
||||||
OBJS += techlibs/anlogic/anlogic_determine_init.o
|
OBJS += techlibs/anlogic/anlogic_fixcarry.o
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
|
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
|
||||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
|
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* yosys -- Yosys Open SYnthesis Suite
|
|
||||||
*
|
|
||||||
* Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
struct AnlogicDetermineInitPass : public Pass {
|
|
||||||
AnlogicDetermineInitPass() : Pass("anlogic_determine_init", "Anlogic: Determine the init value of cells") { }
|
|
||||||
void help() YS_OVERRIDE
|
|
||||||
{
|
|
||||||
log("\n");
|
|
||||||
log(" anlogic_determine_init [selection]\n");
|
|
||||||
log("\n");
|
|
||||||
log("Determine the init value of cells that doesn't allow unknown init value.\n");
|
|
||||||
log("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
Const determine_init(Const init)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < GetSize(init); i++) {
|
|
||||||
if (init[i] != State::S0 && init[i] != State::S1)
|
|
||||||
init[i] = State::S0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return init;
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
|
||||||
{
|
|
||||||
log_header(design, "Executing ANLOGIC_DETERMINE_INIT pass (determine init value for cells).\n");
|
|
||||||
|
|
||||||
extra_args(args, args.size(), design);
|
|
||||||
|
|
||||||
int cnt = 0;
|
|
||||||
for (auto module : design->selected_modules())
|
|
||||||
{
|
|
||||||
for (auto cell : module->selected_cells())
|
|
||||||
{
|
|
||||||
if (cell->type == "\\EG_LOGIC_DRAM16X4")
|
|
||||||
{
|
|
||||||
cell->setParam("\\INIT_D0", determine_init(cell->getParam("\\INIT_D0")));
|
|
||||||
cell->setParam("\\INIT_D1", determine_init(cell->getParam("\\INIT_D1")));
|
|
||||||
cell->setParam("\\INIT_D2", determine_init(cell->getParam("\\INIT_D2")));
|
|
||||||
cell->setParam("\\INIT_D3", determine_init(cell->getParam("\\INIT_D3")));
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log_header(design, "Updated %d cells with determined init value.\n", cnt);
|
|
||||||
}
|
|
||||||
} AnlogicDetermineInitPass;
|
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_END
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
static SigBit get_bit_or_zero(const SigSpec &sig)
|
||||||
|
{
|
||||||
|
if (GetSize(sig) == 0)
|
||||||
|
return State::S0;
|
||||||
|
return sig[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fix_carry_chain(Module *module)
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
pool<SigBit> ci_bits;
|
||||||
|
dict<SigBit, SigBit> mapping_bits;
|
||||||
|
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\AL_MAP_ADDER") {
|
||||||
|
if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0) {
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigSpec o = cell->getPort("\\o");
|
||||||
|
if (GetSize(o) == 2) {
|
||||||
|
SigBit bit_o = o[0];
|
||||||
|
ci_bits.insert(bit_ci);
|
||||||
|
mapping_bits[bit_ci] = bit_o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<Cell*> adders_to_fix_cells;
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\AL_MAP_ADDER") {
|
||||||
|
if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
if (!ci_bits.count(canonical_bit))
|
||||||
|
continue;
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
adders_to_fix_cells.push_back(cell);
|
||||||
|
log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto cell : adders_to_fix_cells)
|
||||||
|
{
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
auto bit = mapping_bits.at(canonical_bit);
|
||||||
|
log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
|
||||||
|
Cell *c = module->addCell(NEW_ID, "\\AL_MAP_ADDER");
|
||||||
|
SigBit new_bit = module->addWire(NEW_ID);
|
||||||
|
SigBit dummy_bit = module->addWire(NEW_ID);
|
||||||
|
SigSpec bits;
|
||||||
|
bits.append(dummy_bit);
|
||||||
|
bits.append(new_bit);
|
||||||
|
c->setParam("\\ALUTYPE", Const("ADD_CARRY"));
|
||||||
|
c->setPort("\\a", bit);
|
||||||
|
c->setPort("\\b", State::S0);
|
||||||
|
c->setPort("\\c", State::S0);
|
||||||
|
c->setPort("\\o", bits);
|
||||||
|
|
||||||
|
cell->setPort("\\c", new_bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AnlogicCarryFixPass : public Pass {
|
||||||
|
AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" anlogic_fixcarry [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Add Anlogic adders to fix carry chain if needed.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
Module *module = design->top_module();
|
||||||
|
|
||||||
|
if (module == nullptr)
|
||||||
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
|
fix_carry_chain(module);
|
||||||
|
}
|
||||||
|
} AnlogicCarryFixPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -31,7 +31,10 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
output [Y_WIDTH-1:0] X, Y;
|
output [Y_WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
input CI, BI;
|
input CI, BI;
|
||||||
output CO;
|
output [Y_WIDTH-1:0] CO;
|
||||||
|
|
||||||
|
wire CIx;
|
||||||
|
wire [Y_WIDTH-1:0] COx;
|
||||||
|
|
||||||
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
||||||
|
|
||||||
|
@ -41,15 +44,16 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
|
|
||||||
wire [Y_WIDTH-1:0] AA = A_buf;
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
wire [Y_WIDTH+1:0] COx;
|
wire [Y_WIDTH-1:0] C = { COx, CIx };
|
||||||
wire [Y_WIDTH+2:0] C = {COx, CI};
|
|
||||||
|
|
||||||
wire dummy;
|
wire dummy;
|
||||||
AL_MAP_ADDER #(
|
AL_MAP_ADDER #(
|
||||||
.ALUTYPE("ADD_CARRY"))
|
.ALUTYPE("ADD_CARRY"))
|
||||||
adder_cin (
|
adder_cin (
|
||||||
.a(C[0]),
|
.a(CI),
|
||||||
.o({COx[0], dummy})
|
.b(1'b0),
|
||||||
|
.c(1'b0),
|
||||||
|
.o({CIx, dummy})
|
||||||
);
|
);
|
||||||
|
|
||||||
genvar i;
|
genvar i;
|
||||||
|
@ -59,18 +63,22 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
) adder_i (
|
) adder_i (
|
||||||
.a(AA[i]),
|
.a(AA[i]),
|
||||||
.b(BB[i]),
|
.b(BB[i]),
|
||||||
.c(C[i+1]),
|
.c(C[i]),
|
||||||
.o({COx[i+1],Y[i]})
|
.o({COx[i],Y[i]})
|
||||||
);
|
);
|
||||||
end: slice
|
|
||||||
|
wire cout;
|
||||||
|
AL_MAP_ADDER #(
|
||||||
|
.ALUTYPE("ADD"))
|
||||||
|
adder_cout (
|
||||||
|
.a(1'b0),
|
||||||
|
.b(1'b0),
|
||||||
|
.c(COx[i]),
|
||||||
|
.o({cout, CO[i]})
|
||||||
|
);
|
||||||
|
end: slice
|
||||||
endgenerate
|
endgenerate
|
||||||
/* End implementation */
|
|
||||||
AL_MAP_ADDER #(
|
/* End implementation */
|
||||||
.ALUTYPE("ADD"))
|
assign X = AA ^ BB;
|
||||||
adder_cout (
|
|
||||||
.c(C[Y_WIDTH+1]),
|
|
||||||
.o(COx[Y_WIDTH+1])
|
|
||||||
);
|
|
||||||
assign CO = COx[Y_WIDTH+1];
|
|
||||||
assign X = AA ^ BB;
|
|
||||||
endmodule
|
endmodule
|
|
@ -154,7 +154,7 @@ struct SynthAnlogicPass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("memory_bram -rules +/anlogic/drams.txt");
|
run("memory_bram -rules +/anlogic/drams.txt");
|
||||||
run("techmap -map +/anlogic/drams_map.v");
|
run("techmap -map +/anlogic/drams_map.v");
|
||||||
run("anlogic_determine_init");
|
run("setundef -zero -params t:EG_LOGIC_DRAM16X4");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("fine"))
|
if (check_label("fine"))
|
||||||
|
@ -186,6 +186,11 @@ struct SynthAnlogicPass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("techmap -map +/anlogic/cells_map.v");
|
run("techmap -map +/anlogic/cells_map.v");
|
||||||
run("clean");
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_anlogic"))
|
||||||
|
{
|
||||||
|
run("anlogic_fixcarry");
|
||||||
run("anlogic_eqn");
|
run("anlogic_eqn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue