From ef7594ce3d3b0fbf08941fb8d4010e73652afd97 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 12 May 2017 22:36:53 +0200 Subject: Improve simplec back-end --- backends/simplec/simplec.cc | 86 ++++++++++++++++++++++++++++++++++++++------ backends/simplec/test00.sh | 2 +- backends/simplec/test00_tb.c | 2 +- 3 files changed, 78 insertions(+), 12 deletions(-) diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index 2b7f4d86b..df53b4d89 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -19,6 +19,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include "kernel/utils.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -134,6 +135,8 @@ struct SimplecWorker dict>>> bit2cell; dict>> bit2output; + dict topoidx; + SimplecWorker(Design *design) : design(design) { } @@ -290,11 +293,49 @@ struct SimplecWorker create_module_struct(design->module(c->type)); } + TopoSort topo; + + for (Cell *c : mod->cells()) + { + topo.node(c->name); + + for (auto &conn : c->connections()) + { + if (!c->input(conn.first)) + continue; + + for (auto bit : sigmaps.at(mod)(conn.second)) + for (auto &it : bit2cell[mod][bit]) + topo.edge(c->name, std::get<0>(it)->name); + } + } + + topo.analyze_loops = false; + topo.sort(); + + for (int i = 0; i < GetSize(topo.sorted); i++) + topoidx[mod->cell(topo.sorted[i])] = i; + + struct_declarations.push_back(""); + struct_declarations.push_back(stringf("struct %s_state_t", cid(mod->name).c_str())); + struct_declarations.push_back("{"); + + struct_declarations.push_back(" // Input Ports"); + for (Wire *w : mod->wires()) + if (w->port_input) + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w))); + struct_declarations.push_back(""); - struct_declarations.push_back(stringf("struct %s_state_t {", cid(mod->name).c_str())); + struct_declarations.push_back(" // Output Ports"); + for (Wire *w : mod->wires()) + if (!w->port_input && w->port_output) + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w))); + struct_declarations.push_back(""); + struct_declarations.push_back(" // Internal Wires"); for (Wire *w : mod->wires()) - struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w))); + if (!w->port_input && !w->port_output) + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w))); for (Cell *c : mod->cells()) if (design->module(c->type)) @@ -303,7 +344,7 @@ struct SimplecWorker struct_declarations.push_back(stringf("};")); } - void eval_cell(HierDirtyFlags *work, string &prefix, string &/* log_prefix */, Cell *cell) + void eval_cell(HierDirtyFlags *work, const string &prefix, const string &/* log_prefix */, Cell *cell) { if (cell->type.in("$_BUF_", "$_NOT_")) { @@ -420,10 +461,13 @@ struct SimplecWorker log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type)); } - void eval_dirty(HierDirtyFlags *work, string prefix, string log_prefix, string parent_prefix) + void eval_dirty(HierDirtyFlags *work, const string &prefix, const string &log_prefix, const string &parent_prefix, const string &parent_log_prefix) { while (work->dirty) { + if (verbose && (!work->dirty_bits.empty() || !work->dirty_cells.empty())) + log("In %s:\n", log_prefix.c_str()); + while (!work->dirty_bits.empty() || !work->dirty_cells.empty()) { if (!work->dirty_bits.empty()) @@ -431,8 +475,11 @@ struct SimplecWorker SigSpec dirtysig(work->dirty_bits); dirtysig.sort_and_unify(); - for (SigChunk chunk : dirtysig.chunks()) - funct_declarations.push_back(stringf(" // New dirty bits in %s: %s", log_prefix.c_str(), log_signal(chunk))); + for (SigChunk chunk : dirtysig.chunks()) { + if (verbose) + log(" Propagating %s.%s[%d:%d].\n", log_prefix.c_str(), log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset); + funct_declarations.push_back(stringf(" // Updated signal in %s: %s", log_prefix.c_str(), log_signal(chunk))); + } for (SigBit bit : dirtysig) { @@ -453,21 +500,34 @@ struct SimplecWorker util_get_bit(bit.wire->width, bit.offset).c_str(), (prefix + cid(bit.wire->name)).c_str())); work->parent->set_dirty(parent_bit); + + if (verbose) + log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", log_prefix.c_str(), log_id(bit.wire), bit.offset, + parent_log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset); } for (auto &port : bit2cell[work->module][bit]) { - if (work->children.count(std::get<0>(port)->name)) { + if (work->children.count(std::get<0>(port)->name)) + { HierDirtyFlags *child = work->children.at(std::get<0>(port)->name); SigBit child_bit = sigmaps.at(child->module)(SigBit(child->module->wire(std::get<1>(port)), std::get<2>(port))); log_assert(bit.wire && child_bit.wire); + funct_declarations.push_back(stringf(" %s(&%s, %s(&%s));", util_set_bit(child_bit.wire->width, child_bit.offset).c_str(), (prefix + cid(child->hiername) + "." + cid(child_bit.wire->name)).c_str(), util_get_bit(bit.wire->width, bit.offset).c_str(), (prefix + cid(bit.wire->name)).c_str())); child->set_dirty(child_bit); + + if (verbose) + log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", log_prefix.c_str(), log_id(bit.wire), bit.offset, + log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset); } else { + if (verbose) + log(" Marking cell %s.%s (via %s.%s[%d]).\n", log_prefix.c_str(), log_id(std::get<0>(port)), + log_prefix.c_str(), log_id(bit.wire), bit.offset); work->set_dirty(std::get<0>(port)); } } @@ -477,14 +537,20 @@ struct SimplecWorker if (!work->dirty_cells.empty()) { - Cell *cell = *work->dirty_cells.begin(); + Cell *cell = nullptr; + for (auto c : work->dirty_cells) + if (cell == nullptr || topoidx.at(cell) < topoidx.at(c)) + cell = c; + + if (verbose) + log(" Evaluating %s.%s (%s, best of %d).\n", log_prefix.c_str(), log_id(cell), log_id(cell->type), GetSize(work->dirty_cells)); eval_cell(work, prefix, log_prefix, cell); work->unset_dirty(cell); } } for (auto &child : work->children) - eval_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first), prefix); + eval_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first), prefix, log_prefix); } } @@ -509,7 +575,7 @@ struct SimplecWorker dirty_flags->set_dirty(bit); } - eval_dirty(dirty_flags, "state->", log_id(mod), ""); + eval_dirty(dirty_flags, "state->", log_id(mod), "", ""); funct_declarations.push_back("}"); diff --git a/backends/simplec/test00.sh b/backends/simplec/test00.sh index 6a7560da0..ede757273 100644 --- a/backends/simplec/test00.sh +++ b/backends/simplec/test00.sh @@ -1,5 +1,5 @@ #!/bin/bash set -ex -../../yosys -p 'synth -top test; write_simplec -i8 test00_uut.c' test00_uut.v +../../yosys -p 'synth -top test; write_simplec -verbose -i8 test00_uut.c' test00_uut.v clang -o test00_tb test00_tb.c ./test00_tb diff --git a/backends/simplec/test00_tb.c b/backends/simplec/test00_tb.c index 650f121ca..9b3ae00e0 100644 --- a/backends/simplec/test00_tb.c +++ b/backends/simplec/test00_tb.c @@ -16,7 +16,7 @@ int main() struct test_state_t state; uint32_t a, b, c, x, y, z; - for (int i = 0; i < 100; i++) + for (int i = 0; i < 10; i++) { a = xorshift32(); b = xorshift32(); -- cgit v1.2.3