3
0
Fork 0
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:
Eddie Hung 2019-03-14 08:59:19 -07:00
commit f1a8e8a480
82 changed files with 2492 additions and 593 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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 $^ $@

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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
View 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

View file

@ -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"))

View file

@ -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");