mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-24 01:25:33 +00:00
Merge remote-tracking branch 'origin/master' into xc7srl
This commit is contained in:
commit
f1a8e8a480
82 changed files with 2492 additions and 593 deletions
|
@ -910,7 +910,7 @@ struct HierarchyPass : public Pass {
|
|||
if (m == nullptr)
|
||||
continue;
|
||||
|
||||
if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty()) {
|
||||
if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
|
||||
IdString new_m_name = m->derive(design, cell->parameters, true);
|
||||
if (new_m_name.empty())
|
||||
continue;
|
||||
|
|
|
@ -53,6 +53,7 @@ struct WreduceWorker
|
|||
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
|
||||
std::set<SigBit> work_queue_bits;
|
||||
pool<SigBit> keep_bits;
|
||||
dict<SigBit, State> init_bits;
|
||||
|
||||
WreduceWorker(WreduceConfig *config, Module *module) :
|
||||
config(config), module(module), mi(module) { }
|
||||
|
@ -141,6 +142,7 @@ struct WreduceWorker
|
|||
|
||||
SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
|
||||
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
|
||||
Const initval;
|
||||
|
||||
int width_before = GetSize(sig_q);
|
||||
|
||||
|
@ -150,16 +152,24 @@ struct WreduceWorker
|
|||
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
|
||||
bool sign_ext = !zero_ext;
|
||||
|
||||
for (int i = 0; i < GetSize(sig_q); i++) {
|
||||
SigBit bit = sig_q[i];
|
||||
if (init_bits.count(bit))
|
||||
initval.bits.push_back(init_bits.at(bit));
|
||||
else
|
||||
initval.bits.push_back(State::Sx);
|
||||
}
|
||||
|
||||
for (int i = GetSize(sig_q)-1; i >= 0; i--)
|
||||
{
|
||||
if (zero_ext && sig_d[i] == State::S0) {
|
||||
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) {
|
||||
module->connect(sig_q[i], State::S0);
|
||||
sig_d.remove(i);
|
||||
sig_q.remove(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) {
|
||||
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) {
|
||||
module->connect(sig_q[i], sig_q[i-1]);
|
||||
sig_d.remove(i);
|
||||
sig_q.remove(i);
|
||||
|
@ -167,7 +177,7 @@ struct WreduceWorker
|
|||
}
|
||||
|
||||
auto info = mi.query(sig_q[i]);
|
||||
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
|
||||
if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
|
||||
sig_d.remove(i);
|
||||
sig_q.remove(i);
|
||||
zero_ext = false;
|
||||
|
@ -183,10 +193,11 @@ struct WreduceWorker
|
|||
|
||||
if (GetSize(sig_q) == 0) {
|
||||
log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
|
||||
module->remove(cell);
|
||||
return;
|
||||
}
|
||||
|
||||
log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
|
||||
log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
|
||||
log_id(module), log_id(cell), log_id(cell->type));
|
||||
|
||||
for (auto bit : sig_d)
|
||||
|
@ -376,10 +387,18 @@ struct WreduceWorker
|
|||
|
||||
void run()
|
||||
{
|
||||
for (auto w : module->wires())
|
||||
for (auto w : module->wires()) {
|
||||
if (w->get_bool_attribute("\\keep"))
|
||||
for (auto bit : mi.sigmap(w))
|
||||
keep_bits.insert(bit);
|
||||
if (w->attributes.count("\\init")) {
|
||||
Const initval = w->attributes.at("\\init");
|
||||
SigSpec initsig = mi.sigmap(w);
|
||||
int width = std::min(GetSize(initval), GetSize(initsig));
|
||||
for (int i = 0; i < width; i++)
|
||||
init_bits[initsig[i]] = initval[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (auto c : module->selected_cells())
|
||||
work_queue_cells.insert(c);
|
||||
|
|
|
@ -4,5 +4,5 @@ passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_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/ice40_dsp.pmg passes/pmgen/pmgen.py
|
||||
$(P) cd passes/pmgen && python3 pmgen.py ice40_dsp
|
||||
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
|
||||
$(P) mkdir -p passes/pmgen && python3 $^ $@
|
||||
|
|
|
@ -16,7 +16,7 @@ API of Generated Matcher
|
|||
========================
|
||||
|
||||
When `pmgen.py` reads a `foobar.pmg` file, it writes `foobar_pm.h` containing
|
||||
a class `foobar_pm`. That class is instanciated with an RTLIL module and a
|
||||
a class `foobar_pm`. That class is instantiated with an RTLIL module and a
|
||||
list of cells from that module:
|
||||
|
||||
foobar_pm pm(module, module->selected_cells());
|
||||
|
@ -142,7 +142,7 @@ The `select` lines are evaluated once for each cell when the matcher is
|
|||
initialized. A `match` block will only consider cells for which all `select`
|
||||
expressions evaluated to `true`. Note that the state variable corresponding to
|
||||
the match (in the example `mul`) is the only state variable that may be used
|
||||
`select` lines.
|
||||
in `select` lines.
|
||||
|
||||
Index lines are using the `index <type> expr1 === expr2` syntax. `expr1` is
|
||||
evaluated during matcher initialization and the same restrictions apply as for
|
||||
|
|
|
@ -6,7 +6,11 @@ import pprint
|
|||
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
|
||||
prefix = sys.argv[1]
|
||||
pmgfile = sys.argv[1]
|
||||
assert pmgfile.endswith(".pmg")
|
||||
prefix = pmgfile[0:-4]
|
||||
prefix = prefix.split('/')[-1]
|
||||
outfile = sys.argv[2]
|
||||
|
||||
state_types = dict()
|
||||
udata_types = dict()
|
||||
|
@ -73,7 +77,7 @@ def rewrite_cpp(s):
|
|||
|
||||
return "".join(t)
|
||||
|
||||
with open("%s.pmg" % prefix, "r") as f:
|
||||
with open(pmgfile, "r") as f:
|
||||
while True:
|
||||
line = f.readline()
|
||||
if line == "": break
|
||||
|
@ -82,7 +86,7 @@ with open("%s.pmg" % prefix, "r") as f:
|
|||
cmd = line.split()
|
||||
if len(cmd) == 0 or cmd[0].startswith("//"): continue
|
||||
cmd = cmd[0]
|
||||
|
||||
|
||||
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)
|
||||
assert m
|
||||
|
@ -176,7 +180,7 @@ with open("%s.pmg" % prefix, "r") as f:
|
|||
|
||||
blocks.append(block)
|
||||
|
||||
with open("%s_pm.h" % prefix, "w") as f:
|
||||
with open(outfile, "w") as f:
|
||||
print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f)
|
||||
print("", file=f)
|
||||
|
||||
|
|
|
@ -8,4 +8,5 @@ OBJS += passes/sat/expose.o
|
|||
OBJS += passes/sat/assertpmux.o
|
||||
OBJS += passes/sat/clk2fflogic.o
|
||||
OBJS += passes/sat/async2sync.o
|
||||
OBJS += passes/sat/supercover.o
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ struct Async2syncPass : public Pass {
|
|||
log("reset value in the next cycle regardless of the data-in value at the time of\n");
|
||||
log("the clock edge.\n");
|
||||
log("\n");
|
||||
log("Currently only $adff cells are supported by this pass.\n");
|
||||
log("Currently only $adff and $dffsr cells are supported by this pass.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
@ -84,7 +84,7 @@ struct Async2syncPass : public Pass {
|
|||
bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool();
|
||||
Const arst_val = cell->parameters["\\ARST_VALUE"];
|
||||
|
||||
SigSpec sig_clk = cell->getPort("\\CLK");
|
||||
// SigSpec sig_clk = cell->getPort("\\CLK");
|
||||
SigSpec sig_arst = cell->getPort("\\ARST");
|
||||
SigSpec sig_d = cell->getPort("\\D");
|
||||
SigSpec sig_q = cell->getPort("\\Q");
|
||||
|
@ -120,6 +120,55 @@ struct Async2syncPass : public Pass {
|
|||
cell->type = "$dff";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type.in("$dffsr"))
|
||||
{
|
||||
// bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool();
|
||||
bool set_pol = cell->parameters["\\SET_POLARITY"].as_bool();
|
||||
bool clr_pol = cell->parameters["\\CLR_POLARITY"].as_bool();
|
||||
|
||||
// SigSpec sig_clk = cell->getPort("\\CLK");
|
||||
SigSpec sig_set = cell->getPort("\\SET");
|
||||
SigSpec sig_clr = cell->getPort("\\CLR");
|
||||
SigSpec sig_d = cell->getPort("\\D");
|
||||
SigSpec sig_q = cell->getPort("\\Q");
|
||||
|
||||
log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n",
|
||||
log_id(module), log_id(cell), log_id(cell->type),
|
||||
log_signal(sig_set), log_signal(sig_clr), log_signal(sig_d), log_signal(sig_q));
|
||||
|
||||
Const init_val;
|
||||
for (int i = 0; i < GetSize(sig_q); i++) {
|
||||
SigBit bit = sigmap(sig_q[i]);
|
||||
init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
|
||||
del_initbits.insert(bit);
|
||||
}
|
||||
|
||||
Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d));
|
||||
Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
|
||||
new_q->attributes["\\init"] = init_val;
|
||||
|
||||
if (!set_pol)
|
||||
sig_set = module->Not(NEW_ID, sig_set);
|
||||
|
||||
if (clr_pol)
|
||||
sig_clr = module->Not(NEW_ID, sig_clr);
|
||||
|
||||
SigSpec tmp = module->Or(NEW_ID, sig_d, sig_set);
|
||||
module->addAnd(NEW_ID, tmp, sig_clr, new_d);
|
||||
|
||||
tmp = module->Or(NEW_ID, new_q, sig_set);
|
||||
module->addAnd(NEW_ID, tmp, sig_clr, sig_q);
|
||||
|
||||
cell->setPort("\\D", new_d);
|
||||
cell->setPort("\\Q", new_q);
|
||||
cell->unsetPort("\\SET");
|
||||
cell->unsetPort("\\CLR");
|
||||
cell->unsetParam("\\SET_POLARITY");
|
||||
cell->unsetParam("\\CLR_POLARITY");
|
||||
cell->type = "$dff";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto wire : module->wires())
|
||||
|
|
92
passes/sat/supercover.cc
Normal file
92
passes/sat/supercover.cc
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
struct SupercoverPass : public Pass {
|
||||
SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" supercover [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This command adds two cover cells for each bit of each selected wire, one\n");
|
||||
log("checking for a hi signal level and one checking for lo level.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
// bool flag_noinit = false;
|
||||
|
||||
log_header(design, "Executing SUPERCOVER pass.\n");
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
// if (args[argidx] == "-noinit") {
|
||||
// flag_noinit = true;
|
||||
// continue;
|
||||
// }
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
SigMap sigmap(module);
|
||||
pool<SigBit> handled_bits;
|
||||
|
||||
int cnt_wire = 0, cnt_bits = 0;
|
||||
log("Adding cover cells to module %s.\n", log_id(module));
|
||||
for (auto wire : module->selected_wires())
|
||||
{
|
||||
bool counted_wire = false;
|
||||
std::string src = wire->get_src_attribute();
|
||||
|
||||
for (auto bit : sigmap(SigSpec(wire)))
|
||||
{
|
||||
if (bit.wire == nullptr)
|
||||
continue;
|
||||
|
||||
if (handled_bits.count(bit))
|
||||
continue;
|
||||
|
||||
SigSpec inv = module->Not(NEW_ID, bit);
|
||||
module->addCover(NEW_ID, bit, State::S1, src);
|
||||
module->addCover(NEW_ID, inv, State::S1, src);
|
||||
|
||||
handled_bits.insert(bit);
|
||||
if (!counted_wire) {
|
||||
counted_wire = false;
|
||||
cnt_wire++;
|
||||
}
|
||||
cnt_bits++;
|
||||
}
|
||||
}
|
||||
log(" added cover cells to %d wires, %d bits.\n", cnt_wire, cnt_bits);
|
||||
}
|
||||
}
|
||||
} SupercoverPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -660,8 +660,8 @@ struct DfflibmapPass : public Pass {
|
|||
map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_");
|
||||
map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_");
|
||||
|
||||
log(" final dff cell mappings:\n");
|
||||
logmap_all();
|
||||
log(" final dff cell mappings:\n");
|
||||
logmap_all();
|
||||
|
||||
for (auto &it : design->modules_)
|
||||
if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox"))
|
||||
|
|
|
@ -132,9 +132,9 @@ static void dump_dot_graph(string filename,
|
|||
pool<RTLIL::SigBit> nodes, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges,
|
||||
pool<RTLIL::SigBit> inputs, pool<RTLIL::SigBit> outputs,
|
||||
std::function<GraphStyle(RTLIL::SigBit)> node_style =
|
||||
[](RTLIL::SigBit) { return GraphStyle{}; },
|
||||
[](RTLIL::SigBit) { return GraphStyle{}; },
|
||||
std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style =
|
||||
[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; },
|
||||
[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; },
|
||||
string name = "")
|
||||
{
|
||||
FILE *f = fopen(filename.c_str(), "w");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue