/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2024 Emily Schmidt * Copyright (C) 2024 National Technology and Engineering Solutions of Sandia, LLC * * 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/functional.h" #include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct MemContentsTest { int addr_width, data_width; MemContents state; using addr_t = MemContents::addr_t; std::map reference; MemContentsTest(int addr_width, int data_width) : addr_width(addr_width), data_width(data_width), state(addr_width, data_width, RTLIL::Const(State::S0, data_width)) {} void check() { state.check(); for(auto addr = 0; addr < (1<second != state[addr]) goto error; } else { if(state.count_range(addr, addr + 1) != 0) goto error; } } return; error: printf("FAIL\n"); int digits = (data_width + 3) / 4; for(auto addr = 0; addr < (1<second : state.default_value(); std::string ref_string = stringf("%.*x", digits, ref_value.as_int()); bool sta_def = state.count_range(addr, addr + 1) == 1; RTLIL::Const sta_value = state[addr]; std::string sta_string = stringf("%.*x", digits, sta_value.as_int()); if(ref_def && sta_def) { if(ref_value == sta_value) printf("%s%s", ref_string.c_str(), string(digits, ' ').c_str()); else printf("%s%s", ref_string.c_str(), sta_string.c_str()); } else if(ref_def) { printf("%s%s", ref_string.c_str(), string(digits, 'M').c_str()); } else if(sta_def) { printf("%s%s", sta_string.c_str(), string(digits, 'X').c_str()); } else { printf("%s", string(2*digits, ' ').c_str()); } printf(" "); if(addr % 8 == 7) printf("\n"); } printf("\n"); //log_abort(); } void clear_range(addr_t begin_addr, addr_t end_addr) { for(auto addr = begin_addr; addr != end_addr; addr++) reference.erase(addr); state.clear_range(begin_addr, end_addr); check(); } void insert_concatenated(addr_t addr, RTLIL::Const const &values) { addr_t words = ((addr_t) values.size() + data_width - 1) / data_width; for(addr_t i = 0; i < words; i++) { reference.erase(addr + i); reference.emplace(addr + i, values.extract(i * data_width, data_width)); } state.insert_concatenated(addr, values); check(); } template void run(Rnd &rnd, int n) { std::uniform_int_distribution addr_dist(0, (1< length_dist(10); std::uniform_int_distribution data_dist(0, ((uint64_t)1< 0) { addr_t low = addr_dist(rnd); //addr_t length = std::min((1< high) std::swap(low, high); if((rnd() & 7) == 0) { log_debug("clear %.2x to %.2x\n", (int)low, (int)high); clear_range(low, high + 1); } else { log_debug("insert %.2x to %.2x\n", (int)low, (int)high); RTLIL::Const values; for(addr_t addr = low; addr <= high; addr++) { RTLIL::Const word(data_dist(rnd), data_width); values.bits().insert(values.bits().end(), word.begin(), word.end()); } insert_concatenated(low, values); } } } }; struct FunctionalTestGeneric : public Pass { FunctionalTestGeneric() : Pass("test_generic", "test the generic compute graph") {} void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log("TODO: add help message\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { log_header(design, "Executing Test Generic.\n"); size_t argidx = 1; extra_args(args, argidx, design); /* MemContentsTest test(8, 16); std::random_device seed_dev; std::mt19937 rnd(23); //seed_dev()); test.run(rnd, 1000); */ for (auto module : design->selected_modules()) { log("Dumping module `%s'.\n", module->name.c_str()); auto fir = Functional::IR::from_module(module); for(auto node : fir) std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n"; for(auto output : fir.all_outputs()) std::cout << RTLIL::unescape_id(output->kind) << " " << RTLIL::unescape_id(output->name) << " = " << RTLIL::unescape_id(output->value().name()) << "\n"; for(auto state : fir.all_states()) std::cout << RTLIL::unescape_id(state->kind) << " " << RTLIL::unescape_id(state->name) << " = " << RTLIL::unescape_id(state->next_value().name()) << "\n"; } } } FunctionalCxxBackend; PRIVATE_NAMESPACE_END