From 9f4fbc5e74747c8973da3a2fd42d2ef40dbe1fa5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 16 May 2017 19:34:07 +0200 Subject: Add _init() function generator to simpleC back-end --- backends/simplec/simplec.cc | 232 +++++++++++++++++++++++++++---------------- backends/simplec/test00_tb.c | 8 +- 2 files changed, 152 insertions(+), 88 deletions(-) (limited to 'backends') diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index c8a812748..15399831e 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -26,6 +26,40 @@ PRIVATE_NAMESPACE_BEGIN struct HierDirtyFlags; +static pool reserved_cids; +static dict id2cid; + +static string cid(IdString id) +{ + if (id2cid.count(id) == 0) + { + string s = id.str(); + if (GetSize(s) < 2) log_abort(); + + if (s[0] == '\\') + s = s.substr(1); + + if ('0' <= s[0] && s[0] <= '9') { + s = "_" + s; + } + + for (int i = 0; i < GetSize(s); i++) { + if ('0' <= s[i] && s[i] <= '9') continue; + if ('A' <= s[i] && s[i] <= 'Z') continue; + if ('a' <= s[i] && s[i] <= 'z') continue; + s[i] = '_'; + } + + while (reserved_cids.count(s)) + s += "_"; + + reserved_cids.insert(s); + id2cid[id] = s; + } + + return id2cid.at(id); +} + struct HierDirtyFlags { int dirty; @@ -36,12 +70,15 @@ struct HierDirtyFlags pool dirty_cells; pool sticky_dirty_bits; dict children; + string prefix, log_prefix; - HierDirtyFlags(Module *module, IdString hiername, HierDirtyFlags *parent) : dirty(0), module(module), hiername(hiername), parent(parent) + HierDirtyFlags(Module *module, IdString hiername, HierDirtyFlags *parent, const string &prefix, const string &log_prefix) : + dirty(0), module(module), hiername(hiername), parent(parent), prefix(prefix), log_prefix(log_prefix) { for (Cell *cell : module->cells()) { Module *mod = module->design->module(cell->type); - if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this); + if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this, + prefix + cid(cell->name) + ".", log_prefix + "." + prefix + log_id(cell->name)); } } @@ -130,11 +167,9 @@ struct SimplecWorker vector funct_declarations; - pool reserved_cids; - dict id2cid; - dict>>> bit2cell; dict>> bit2output; + dict> driven_bits; dict topoidx; @@ -247,37 +282,6 @@ struct SimplecWorker return stringf(" %s(&%s, %s);", util_name.c_str(), signame.c_str(), expr.c_str()); } - string cid(IdString id) - { - if (id2cid.count(id) == 0) - { - string s = id.str(); - if (GetSize(s) < 2) log_abort(); - - if (s[0] == '\\') - s = s.substr(1); - - if ('0' <= s[0] && s[0] <= '9') { - s = "_" + s; - } - - for (int i = 0; i < GetSize(s); i++) { - if ('0' <= s[i] && s[i] <= '9') continue; - if ('A' <= s[i] && s[i] <= 'Z') continue; - if ('a' <= s[i] && s[i] <= 'z') continue; - s[i] = '_'; - } - - while (reserved_cids.count(s)) - s += "_"; - - reserved_cids.insert(s); - id2cid[id] = s; - } - - return id2cid.at(id); - } - void create_module_struct(Module *mod) { if (generated_structs.count(mod->name)) @@ -297,8 +301,11 @@ struct SimplecWorker { for (auto &conn : c->connections()) { - if (!c->input(conn.first)) + if (!c->input(conn.first)) { + for (auto bit : sigmaps.at(mod)(conn.second)) + driven_bits[mod].insert(bit); continue; + } int idx = 0; for (auto bit : sigmaps.at(mod)(conn.second)) @@ -369,21 +376,21 @@ struct SimplecWorker struct_declarations.push_back("#endif"); } - void eval_cell(HierDirtyFlags *work, const string &prefix, const string &/* log_prefix */, Cell *cell) + void eval_cell(HierDirtyFlags *work, Cell *cell) { if (cell->type.in("$_BUF_", "$_NOT_")) { SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); - string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; + string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; string expr; if (cell->type == "$_BUF_") expr = a_expr; if (cell->type == "$_NOT_") expr = "!" + a_expr; log_assert(y.wire); - funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + + funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); work->set_dirty(y); @@ -396,8 +403,8 @@ struct SimplecWorker SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); - string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; - string b_expr = b.wire ? util_get_bit(prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; + string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; + string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; string expr; if (cell->type == "$_AND_") expr = stringf("%s & %s", a_expr.c_str(), b_expr.c_str()); @@ -408,7 +415,7 @@ struct SimplecWorker if (cell->type == "$_XNOR_") expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str()); log_assert(y.wire); - funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + + funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); work->set_dirty(y); @@ -422,16 +429,16 @@ struct SimplecWorker SigBit c = sigmaps.at(work->module)(cell->getPort("\\C")); SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); - string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; - string b_expr = b.wire ? util_get_bit(prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; - string c_expr = c.wire ? util_get_bit(prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0"; + string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; + string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; + string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0"; string expr; if (cell->type == "$_AOI3_") expr = stringf("!((%s & %s) | %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str()); if (cell->type == "$_OAI3_") expr = stringf("!((%s | %s) & %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str()); log_assert(y.wire); - funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + + funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); work->set_dirty(y); @@ -446,17 +453,17 @@ struct SimplecWorker SigBit d = sigmaps.at(work->module)(cell->getPort("\\D")); SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); - string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; - string b_expr = b.wire ? util_get_bit(prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; - string c_expr = c.wire ? util_get_bit(prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0"; - string d_expr = d.wire ? util_get_bit(prefix + cid(d.wire->name), d.wire->width, d.offset) : d.data ? "1" : "0"; + string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; + string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; + string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0"; + string d_expr = d.wire ? util_get_bit(work->prefix + cid(d.wire->name), d.wire->width, d.offset) : d.data ? "1" : "0"; string expr; if (cell->type == "$_AOI4_") expr = stringf("!((%s & %s) | (%s & %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str()); if (cell->type == "$_OAI4_") expr = stringf("!((%s | %s) & (%s | %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str()); log_assert(y.wire); - funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + + funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); work->set_dirty(y); @@ -470,13 +477,13 @@ struct SimplecWorker SigBit s = sigmaps.at(work->module)(cell->getPort("\\S")); SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); - string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; - string b_expr = b.wire ? util_get_bit(prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; - string s_expr = s.wire ? util_get_bit(prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0"; + string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; + string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; + string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0"; string expr = stringf("%s ? %s : %s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str()); log_assert(y.wire); - funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + + funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); work->set_dirty(y); @@ -486,12 +493,12 @@ struct SimplecWorker log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type)); } - void eval_dirty(HierDirtyFlags *work, const string &prefix, const string &log_prefix, const string &parent_prefix, const string &parent_log_prefix) + void eval_dirty(HierDirtyFlags *work) { while (work->dirty) { if (verbose && (!work->dirty_bits.empty() || !work->dirty_cells.empty())) - log(" In %s:\n", log_prefix.c_str()); + log(" In %s:\n", work->log_prefix.c_str()); while (!work->dirty_bits.empty() || !work->dirty_cells.empty()) { @@ -501,9 +508,11 @@ struct SimplecWorker dirtysig.sort_and_unify(); for (SigChunk chunk : dirtysig.chunks()) { + if (chunk.wire == nullptr) + continue; 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))); + log(" Propagating %s.%s[%d:%d].\n", work->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", work->log_prefix.c_str(), log_signal(chunk))); } for (SigBit bit : dirtysig) @@ -519,13 +528,13 @@ struct SimplecWorker SigBit parent_bit = sigmaps.at(parent_mod)(parent_cell->getPort(port_name)[port_offset]); log_assert(bit.wire && parent_bit.wire); - funct_declarations.push_back(util_set_bit(parent_prefix + cid(parent_bit.wire->name), parent_bit.wire->width, parent_bit.offset, - util_get_bit(prefix + cid(bit.wire->name), bit.wire->width, bit.offset))); + funct_declarations.push_back(util_set_bit(work->parent->prefix + cid(parent_bit.wire->name), parent_bit.wire->width, parent_bit.offset, + util_get_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset))); 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); + log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset, + work->parent->log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset); } for (auto &port : bit2cell[work->module][bit]) @@ -536,17 +545,17 @@ struct SimplecWorker 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(util_set_bit(prefix + cid(child->hiername) + "." + cid(child_bit.wire->name), - child_bit.wire->width, child_bit.offset, util_get_bit(prefix + cid(bit.wire->name), bit.wire->width, bit.offset))); + funct_declarations.push_back(util_set_bit(work->prefix + cid(child->hiername) + "." + cid(child_bit.wire->name), + child_bit.wire->width, child_bit.offset, util_get_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset))); 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); + log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset, + work->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); + log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix.c_str(), log_id(std::get<0>(port)), + work->log_prefix.c_str(), log_id(bit.wire), bit.offset); work->set_dirty(std::get<0>(port)); } } @@ -561,7 +570,7 @@ struct SimplecWorker if (cell == nullptr || topoidx.at(cell) < topoidx.at(c)) cell = c; - string hiername = log_prefix + "." + log_id(cell); + string hiername = work->log_prefix + "." + log_id(cell); if (verbose) log(" Evaluating %s (%s, best of %d).\n", hiername.c_str(), log_id(cell->type), GetSize(work->dirty_cells)); @@ -570,17 +579,17 @@ struct SimplecWorker reactivated_cells.insert(hiername); activated_cells.insert(hiername); - eval_cell(work, prefix, log_prefix, cell); + eval_cell(work, cell); work->unset_dirty(cell); } } for (auto &child : work->children) - eval_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first), prefix, log_prefix); + eval_dirty(child.second); } } - void eval_sticky_dirty(HierDirtyFlags *work, const string &prefix, const string &log_prefix) + void eval_sticky_dirty(HierDirtyFlags *work) { Module *mod = work->module; @@ -595,23 +604,25 @@ struct SimplecWorker if (work->sticky_dirty_bits.count(canonical_bit) == 0) continue; - log_assert(bit.wire && canonical_bit.wire); - funct_declarations.push_back(util_set_bit(prefix + cid(bit.wire->name), bit.wire->width, bit.offset, - util_get_bit(prefix + cid(canonical_bit.wire->name), canonical_bit.wire->width, canonical_bit.offset).c_str())); + if (bit.wire == nullptr || canonical_bit.wire == nullptr) + continue; + + funct_declarations.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, + util_get_bit(work->prefix + cid(canonical_bit.wire->name), canonical_bit.wire->width, canonical_bit.offset).c_str())); if (verbose) log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n", - log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset, - log_prefix.c_str(), log_id(bit.wire), bit.offset); + work->log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset, + work->log_prefix.c_str(), log_id(bit.wire), bit.offset); } work->sticky_dirty_bits.clear(); for (auto &child : work->children) - eval_sticky_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first)); + eval_sticky_dirty(child.second); } - void make_func(HierDirtyFlags *work, const string &func_name) + void make_func(HierDirtyFlags *work, const string &func_name, const vector &preamble) { log("Generating function %s():\n", func_name.c_str()); @@ -621,21 +632,65 @@ struct SimplecWorker funct_declarations.push_back(""); funct_declarations.push_back(stringf("static void %s(struct %s_state_t *state)", func_name.c_str(), cid(work->module->name).c_str())); funct_declarations.push_back("{"); - eval_dirty(work, "state->", log_id(work->module->name), "", ""); - eval_sticky_dirty(work, "state->", log_id(work->module->name)); + for (auto &line : preamble) + funct_declarations.push_back(line); + eval_dirty(work); + eval_sticky_dirty(work); funct_declarations.push_back("}"); log(" Activated %d cells (%d activated more than once).\n", GetSize(activated_cells), GetSize(reactivated_cells)); } - void make_init_func(HierDirtyFlags* /* work */) + void eval_init(HierDirtyFlags *work, vector &preamble) { - // FIXME + Module *module = work->module; + + for (Wire *w : module->wires()) + { + if (w->attributes.count("\\init")) + { + SigSpec sig = sigmaps.at(module)(w); + Const val = w->attributes.at("\\init"); + val.bits.resize(GetSize(sig), State::Sx); + + for (int i = 0; i < GetSize(sig); i++) + if (val[i] == State::S0 || val[i] == State::S1) { + SigBit bit = sig[i]; + preamble.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, val == State::S1 ? "true" : "false")); + work->set_dirty(bit); + } + } + + for (SigBit bit : SigSpec(w)) + { + SigBit val = sigmaps.at(module)(bit); + + if (val == State::S0 || val == State::S1) + preamble.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, val == State::S1 ? "true" : "false")); + + if (driven_bits.at(module).count(val) == 0) + work->set_dirty(val); + } + } + + work->set_dirty(State::S0); + work->set_dirty(State::S1); + + for (auto &child : work->children) + eval_init(child.second, preamble); + } + + void make_init_func(HierDirtyFlags *work) + { + vector preamble; + eval_init(work, preamble); + make_func(work, cid(work->module->name) + "_init", preamble); } void make_eval_func(HierDirtyFlags *work) { Module *mod = work->module; + vector preamble; for (Wire *w : mod->wires()) { if (w->port_input) @@ -643,7 +698,7 @@ struct SimplecWorker work->set_dirty(bit); } - make_func(work, cid(work->module->name) + "_eval"); + make_func(work, cid(work->module->name) + "_eval", preamble); } void make_tick_func(HierDirtyFlags* /* work */) @@ -655,7 +710,7 @@ struct SimplecWorker { create_module_struct(mod); - HierDirtyFlags work(mod, IdString(), nullptr); + HierDirtyFlags work(mod, IdString(), nullptr, "state->", log_id(mod->name)); make_init_func(&work); make_eval_func(&work); @@ -704,6 +759,9 @@ struct SimplecBackend : public Backend { } virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) { + reserved_cids.clear(); + id2cid.clear(); + SimplecWorker worker(design); log_header(design, "Executing SIMPLEC backend.\n"); diff --git a/backends/simplec/test00_tb.c b/backends/simplec/test00_tb.c index 7d86d0d91..7fac48265 100644 --- a/backends/simplec/test00_tb.c +++ b/backends/simplec/test00_tb.c @@ -15,6 +15,7 @@ int main() { struct test_state_t state; uint32_t a, b, c, x, y, z, w; + bool first_eval = true; for (int i = 0; i < 10; i++) { @@ -42,7 +43,12 @@ int main() state.c.value_23_16 = c >> 16; state.c.value_31_24 = c >> 24; - test_eval(&state); + if (first_eval) { + first_eval = false; + test_init(&state); + } else { + test_eval(&state); + } uint32_t uut_x = 0; uut_x |= (uint32_t)state.x.value_7_0; -- cgit v1.2.3