Merge branch 'eddie/split_shiftx' into xc7mux

This commit is contained in:
Eddie Hung 2019-04-25 17:31:27 -07:00
commit 3042d58330
9 changed files with 149 additions and 14 deletions

View File

@ -370,7 +370,7 @@ Verilog Attributes and non-standard features
- When defining a macro with `define, all text between triple double quotes - When defining a macro with `define, all text between triple double quotes
is interpreted as macro body, even if it contains unescaped newlines. The is interpreted as macro body, even if it contains unescaped newlines. The
tipple double quotes are removed from the macro body. For example: triple double quotes are removed from the macro body. For example:
`define MY_MACRO(a, b) """ `define MY_MACRO(a, b) """
assign a = 23; assign a = 23;
@ -457,7 +457,7 @@ Non-standard or SystemVerilog features for formal verification
supported in any clocked block. supported in any clocked block.
- The syntax ``@($global_clock)`` can be used to create FFs that have no - The syntax ``@($global_clock)`` can be used to create FFs that have no
explicit clock input ($ff cells). The same can be achieved by using explicit clock input (``$ff`` cells). The same can be achieved by using
``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>`` ``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>``
is marked with the ``(* gclk *)`` Verilog attribute. is marked with the ``(* gclk *)`` Verilog attribute.
@ -470,7 +470,7 @@ from SystemVerilog:
- The ``assert`` statement from SystemVerilog is supported in its most basic - The ``assert`` statement from SystemVerilog is supported in its most basic
form. In module context: ``assert property (<expression>);`` and within an form. In module context: ``assert property (<expression>);`` and within an
always block: ``assert(<expression>);``. It is transformed to a $assert cell. always block: ``assert(<expression>);``. It is transformed to an ``$assert`` cell.
- The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are - The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are
also supported. The same limitations as with the ``assert`` statement apply. also supported. The same limitations as with the ``assert`` statement apply.

View File

@ -453,7 +453,7 @@ Aig::Aig(Cell *cell)
int B = mk.inport("\\B"); int B = mk.inport("\\B");
int C = mk.inport("\\C"); int C = mk.inport("\\C");
int D = mk.inport("\\D"); int D = mk.inport("\\D");
int Y = mk.nand_gate(mk.nor_gate(A, B), mk.nor_gate(C, D)); int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D));
mk.outport(Y, "\\Y"); mk.outport(Y, "\\Y");
goto optimize; goto optimize;
} }

View File

@ -464,7 +464,7 @@ struct CellTypes
if (cell->type == "$_AOI4_") if (cell->type == "$_AOI4_")
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
if (cell->type == "$_OAI4_") if (cell->type == "$_OAI4_")
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_or(arg3, arg4, false, false, 1), false, false, 1));
log_assert(arg4.bits.size() == 0); log_assert(arg4.bits.size() == 0);
return eval(cell, arg1, arg2, arg3, errp); return eval(cell, arg1, arg2, arg3, errp);

View File

@ -462,12 +462,10 @@ struct WreduceWorker
SigSpec initsig = init_attr_sigmap(w); SigSpec initsig = init_attr_sigmap(w);
int width = std::min(GetSize(initval), GetSize(initsig)); int width = std::min(GetSize(initval), GetSize(initsig));
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
log_dump(initsig[i], remove_init_bits.count(initsig[i]));
if (!remove_init_bits.count(initsig[i])) if (!remove_init_bits.count(initsig[i]))
new_initval[i] = initval[i]; new_initval[i] = initval[i];
} }
w->attributes.at("\\init") = new_initval; w->attributes.at("\\init") = new_initval;
log_dump(w->name, initval, new_initval);
} }
} }
} }

View File

@ -1 +1 @@
/ice40_dsp_pm.h *_pm.h

View File

@ -1,8 +1,11 @@
OBJS += passes/pmgen/ice40_dsp.o PMG_SRC = $(wildcard passes/pmgen/*.pmg)
PMG_OBJS += $(patsubst %.pmg, %.o, $(PMG_SRC))
OBJS += $(PMG_OBJS)
passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h $(PMG_OBJS): %.o: %_pm.h
EXTRA_OBJS += 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 EXTRA_OBJS += $(patsubst %.pmg, %_pm.h, $(PMG_SRC))
.SECONDARY: $(EXTRA_OBJS)
%_pm.h: passes/pmgen/pmgen.py %.pmg
$(P) mkdir -p passes/pmgen && python3 $^ $@ $(P) mkdir -p passes/pmgen && python3 $^ $@

View File

@ -220,5 +220,5 @@ But in some cases it is more natural to utilize the implicit branch statement:
portAB = \B; portAB = \B;
endcode endcode
There is an implicit `code..endcode` block at the end of each `.pgm` file There is an implicit `code..endcode` block at the end of each `.pmg` file
that just accepts everything that gets all the way there. that just accepts everything that gets all the way there.

View File

@ -0,0 +1,78 @@
/*
* 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"
#include "passes/pmgen/split_shiftx_pm.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
void create_split_shiftx(split_shiftx_pm &pm)
{
if (pm.st.shiftxB.empty())
return;
log_assert(pm.st.shiftx);
SigSpec A = pm.st.shiftx->getPort("\\A");
SigSpec Y = pm.st.shiftx->getPort("\\Y");
const int A_WIDTH = pm.st.shiftx->getParam("\\A_WIDTH").as_int();
const int Y_WIDTH = pm.st.shiftx->getParam("\\Y_WIDTH").as_int();
log_assert(Y_WIDTH > 1);
std::vector<SigBit> bits;
bits.resize(A_WIDTH / Y_WIDTH);
for (int i = 0; i < Y_WIDTH; ++i) {
for (int j = 0; j < A_WIDTH/Y_WIDTH; ++j)
bits[j] = A[j*Y_WIDTH + i];
pm.module->addShiftx(NEW_ID, bits, pm.st.shiftxB, Y[i]);
}
pm.st.shiftx->unsetPort("\\Y");
pm.autoremove(pm.st.shiftx);
pm.autoremove(pm.st.macc);
}
struct BitblastShiftxPass : public Pass {
BitblastShiftxPass() : Pass("split_shiftx", "Split up multi-bit $shiftx cells") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" split_shiftx [selection]\n");
log("\n");
log("Split up $shiftx cells where Y_WIDTH > 1, with consideration for any $macc\n");
log("cells that may be driving their B inputs.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing SPLIT_SHIFTX pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
break;
}
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
split_shiftx_pm(module, module->selected_cells()).run(create_split_shiftx);
}
} BitblastShiftxPass;
PRIVATE_NAMESPACE_END

View File

@ -0,0 +1,56 @@
state <SigSpec> shiftxB
match shiftx
select shiftx->type == $shiftx
select param(shiftx, \Y_WIDTH).as_int() > 1
endmatch
code shiftxB
shiftxB = port(shiftx, \B);
const int b_width = param(shiftx, \B_WIDTH).as_int();
if (param(shiftx, \B_SIGNED) != 0 && shiftxB[b_width-1] == RTLIL::S0)
shiftxB = shiftxB.extract(0, b_width-1);
endcode
match macc
select macc->type == $macc
select param(macc, \B_WIDTH).as_int() == 0
index <SigSpec> port(macc, \Y) === shiftxB
optional
endmatch
code shiftxB
if (macc) {
Const config = param(macc, \CONFIG);
const int config_width = param(macc, \CONFIG_WIDTH).as_int();
const int num_bits = config.extract(0, 4).as_int();
const int num_ports = (config_width - 4) / (2 + 2*num_bits);
if (num_ports != 1) {
shiftxB = nullptr;
reject;
}
// IS_SIGNED?
if (config[4] == 1) {
shiftxB = nullptr;
reject;
}
// DO_SUBTRACT?
if (config[5] == 1) {
shiftxB = nullptr;
reject;
}
const int port_size_A = config.extract(6, num_bits).as_int();
const int port_size_B = config.extract(6 + num_bits, num_bits).as_int();
const SigSpec port_B = port(macc, \A).extract(port_size_A, port_size_B);
if (!port_B.is_fully_const()) {
shiftxB = nullptr;
reject;
}
const int multiply_factor = port_B.as_int();
if (multiply_factor != param(shiftx, \Y_WIDTH).as_int()) {
shiftxB = nullptr;
reject;
}
shiftxB = port(macc, \A).extract(0, port_size_A);
}
endcode