From ddd2366b5a2954aa7642548f814f7bc3a17875eb Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Fri, 16 Aug 2024 18:57:07 +0300 Subject: [PATCH 01/21] Initial DFCxx simulation code was added; options.h was changed to fit the new subcommand. --- src/main.cpp | 40 +++++--- src/model/dfcxx/include/dfcxx/kernel.h | 5 + src/model/dfcxx/lib/dfcxx/kernel.cpp | 5 + src/options.h | 126 ++++++++++++++++++++----- 4 files changed, 143 insertions(+), 33 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9fa311b..796abc2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,29 +19,41 @@ INITIALIZE_EASYLOGGINGPP +// User-defined function to specify functional behaviour of top-level kernel. +std::unique_ptr start(); + //===-----------------------------------------------------------------------===/ // High-Level Synthesis //===-----------------------------------------------------------------------===/ struct HlsContext { - HlsContext(const HlsOptions &options): - options(options) - {} + HlsContext(const HlsOptions &options) : options(options) {} const HlsOptions &options; }; -// User-defined function to specify functional behaviour of top-level kernel. -std::unique_ptr start(); +//===-----------------------------------------------------------------------===/ +// DFCxx Simulation. +//===-----------------------------------------------------------------------===/ -int hlsMain(HlsContext &context) { +struct SimContext { + SimContext(const SimOptions &options): options(options) {} + + const SimOptions &options; +}; + +int hlsMain(const HlsContext &context) { auto kernel = start(); bool useASAP = context.options.asapScheduler; - kernel->compile(context.options.latConfig, - context.options.outNames, - (useASAP) ? dfcxx::Scheduler::ASAP - : dfcxx::Scheduler::Linear); - return 0; + return !kernel->compile(context.options.latConfig, + context.options.outNames, + (useASAP) ? dfcxx::Scheduler::ASAP + : dfcxx::Scheduler::Linear); +} + +int simMain(const SimContext &context) { + auto kernel = start(); + return !kernel->simulate(context.options.dataFiles(), std::cout); } int main(int argc, char **argv) { @@ -63,6 +75,12 @@ int main(int argc, char **argv) { catch(const CLI::ParseError &e) { return options.exit(e); } + + if (options.hls) { + return hlsMain(HlsContext(options.hls)); + } else { + return simMain(SimContext(options.sim)); + } HlsContext context(options.hls); return hlsMain(context); diff --git a/src/model/dfcxx/include/dfcxx/kernel.h b/src/model/dfcxx/include/dfcxx/kernel.h index 1282ba6..e43d22d 100644 --- a/src/model/dfcxx/include/dfcxx/kernel.h +++ b/src/model/dfcxx/include/dfcxx/kernel.h @@ -21,6 +21,8 @@ #include "dfcxx/varbuilders/builder.h" #include "dfcxx/vars/var.h" +#include +#include #include #include @@ -66,6 +68,9 @@ class Kernel { const DFOutputPaths &outputPaths, const Scheduler &sched); + bool simulate(const std::vector &data, + std::ostream &stream); + }; } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index b508fc0..8345758 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -78,4 +78,9 @@ bool Kernel::compile(const DFLatencyConfig &config, return compile(config, outPathsStrings, sched); } +bool Kernel::simulate(const std::vector &data, + std::ostream &stream) { + return true; +} + } // namespace dfcxx diff --git a/src/options.h b/src/options.h index 1ad7e61..ad67e79 100644 --- a/src/options.h +++ b/src/options.h @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -40,10 +41,13 @@ #define OUT_DFCIR_JSON "out_dfcir" #define OUT_FIRRTL_JSON "out_firrtl" +#define SIM_ID_JSON "sim" + //===----------------------------------------------------------------------===// // CLI args/flags definitions #define HLS_CMD "hls" +#define SIM_CMD "sim" #define CONFIG_ARG CLI_ARG("config") #define SCHEDULER_GROUP "scheduler" #define ASAP_SCHEDULER_FLAG CLI_FLAG("a") @@ -54,6 +58,8 @@ #define OUT_DFCIR_ARG CLI_ARG("out-dfcir") #define OUT_FIRRTL_ARG CLI_ARG("out-firrtl") +#define SIM_USAGE_FILES_ARG "files" + //===----------------------------------------------------------------------===// using Json = nlohmann::json; @@ -82,6 +88,10 @@ class AppOptions { virtual void fromJson(Json json) { // TODO: Default implementation. } + + operator bool() const { + return options->parsed(); + } virtual Json toJson() const { return toJson(options); @@ -207,23 +217,6 @@ struct HlsOptions final : public AppOptions { get(json, OUT_DFCIR_JSON, outNames[OUT_FORMAT_ID_INT(DFCIR)]); get(json, OUT_FIRRTL_JSON, outNames[OUT_FORMAT_ID_INT(FIRRTL)]); } - - std::string latConfigFile; - DFLatencyConfig latConfig; - std::vector outNames; - bool asapScheduler; - bool lpScheduler; -}; - -struct Options final : public AppOptions { - Options(const std::string &title, - const std::string &version): - AppOptions(title, version), hls(*this) { - - // Top-level options. - options->set_help_all_flag("-H,--help-all", "Print the extended help message and exit"); - options->set_version_flag("-v,--version", version, "Print the tool version"); - } dfcxx::Ops convertFieldToEnum(const std::string field) { if (field == "ADD_INT") { return dfcxx::ADD_INT; } else @@ -259,22 +252,109 @@ struct Options final : public AppOptions { return dfcxx::ADD_INT; } - void parseLatencyConfig(const std::string config) { - std::ifstream in(config); + void parseLatencyConfig() { + std::ifstream in(latConfigFile); if (!in.good()) { return; } auto json = Json::parse(in); for (auto &[key, val] : json.items()) { - hls.latConfig[convertFieldToEnum(key)] = val; + latConfig[convertFieldToEnum(key)] = val; } } + std::string latConfigFile; + DFLatencyConfig latConfig; + std::vector outNames; + bool asapScheduler; + bool lpScheduler; +}; + +struct SimOptions final : public AppOptions { + + // Custom usage description formatter (based on the default one). + // struct UsageFormatter: public CLI::Formatter { + // inline std::string make_usage(const CLI::App *app, + // std::string name) const override { + // std::stringstream out; + + // out << get_label("Usage") << ":" << (name.empty() ? "" : " ") << name; + + // std::vector groups = app->get_groups(); + + // // Print an Options badge if any options exist + // std::vector non_pos_options = + // app->get_options([](const CLI::Option *opt) { + // return opt->nonpositional(); + // }); + + // if(!non_pos_options.empty()) { + // out << " [" << get_label("OPTIONS") << "]"; + // } + // out << " " SIM_USAGE_FILES_ARG "..."; + + // // Positionals need to be listed here + // std::vector positionals = + // app->get_options([](const CLI::Option *opt) { + // return opt->get_positional(); + // }); + + // // Print out positionals if any are left + // if(!positionals.empty()) { + // // Convert to help names + // std::vector positional_names(positionals.size()); + // std::transform(positionals.begin(), + // positionals.end(), + // positional_names.begin(), + // [this](const CLI::Option *opt) { + // return make_option_usage(opt); + // }); + + // out << " " << CLI::detail::join(positional_names, " "); + // } + + // out << std::endl; + // return out.str(); + // } + // }; + + SimOptions(AppOptions &parent): + AppOptions(parent, SIM_CMD, "DFCxx simulation") { + //options->formatter(std::make_shared()); + // For processing data files' paths. + options->allow_extras(); + auto *var = options; // Used for lambda variable passing. + options->callback([&var]() { + if (var->remaining_size() < 1) { + throw CLI::ArgumentMismatch("input data files", -1, 0); + } + }); + } + + std::vector dataFiles() const { + return options->remaining(); + } +}; + +struct Options final : public AppOptions { + Options(const std::string &title, + const std::string &version): + AppOptions(title, version), hls(*this), sim(*this) { + + // Top-level options. + options->set_help_all_flag("-H,--help-all", "Print the extended help message and exit"); + options->set_version_flag("-v,--version", version, "Print the tool version"); + } + void initialize(const std::string &config, int argc, char **argv) { // Read the JSON configuration. read(config); // Command line is of higher priority. parse(argc, argv); - // Parse latency configuration. - parseLatencyConfig(hls.latConfigFile); + + // Subcommand-specific initialization actions. + if (hls) { + // Parse latency configuration. + hls.parseLatencyConfig(); + } } int exit(const CLI::Error &e) const { @@ -283,7 +363,9 @@ struct Options final : public AppOptions { void fromJson(Json json) override { hls.fromJson(json[HLS_ID_JSON]); + hls.fromJson(json[SIM_ID_JSON]); } HlsOptions hls; + SimOptions sim; }; From 4505cce3c260db165a959850af29a5fd0eb42774 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Fri, 16 Aug 2024 19:01:18 +0300 Subject: [PATCH 02/21] config.json expanded with 'sim'-section. --- config.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config.json b/config.json index 4142592..b8cb3fd 100644 --- a/config.json +++ b/config.json @@ -7,5 +7,8 @@ "out_sv_lib" : "", "out_dfcir" : "", "out_firrtl" : "" + }, + "sim": { + } } From 80a80976a3ce5cb9ea743009724fa5739a03512a Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Fri, 16 Aug 2024 20:50:46 +0300 Subject: [PATCH 03/21] DFCxx node top-sort was moved to utils.h/utils.cpp; DFCIRBuilder was simplified; DFCXXSimulator class was added. --- src/model/dfcxx/include/dfcxx/channel.h | 3 +- src/model/dfcxx/include/dfcxx/kernel.h | 4 +- src/model/dfcxx/include/dfcxx/node.h | 3 +- .../includeDev/dfcxx/IRbuilders/builder.h | 7 +- src/model/dfcxx/includeDev/dfcxx/simulator.h | 23 ++ src/model/dfcxx/includeDev/dfcxx/utils.h | 28 ++ src/model/dfcxx/lib/dfcxx/CMakeLists.txt | 2 + .../dfcxx/lib/dfcxx/IRbuilders/CMakeLists.txt | 1 - .../dfcxx/lib/dfcxx/IRbuilders/builder.cpp | 267 +++++++++++++++- .../dfcxx/lib/dfcxx/IRbuilders/utils.cpp | 295 ------------------ src/model/dfcxx/lib/dfcxx/converter.cpp | 4 + src/model/dfcxx/lib/dfcxx/kernel.cpp | 13 +- src/model/dfcxx/lib/dfcxx/simulator.cpp | 5 + src/model/dfcxx/lib/dfcxx/utils.cpp | 50 +++ 14 files changed, 385 insertions(+), 320 deletions(-) create mode 100644 src/model/dfcxx/includeDev/dfcxx/simulator.h create mode 100644 src/model/dfcxx/includeDev/dfcxx/utils.h delete mode 100644 src/model/dfcxx/lib/dfcxx/IRbuilders/utils.cpp create mode 100644 src/model/dfcxx/lib/dfcxx/simulator.cpp create mode 100644 src/model/dfcxx/lib/dfcxx/utils.cpp diff --git a/src/model/dfcxx/include/dfcxx/channel.h b/src/model/dfcxx/include/dfcxx/channel.h index dd682f7..3477f12 100644 --- a/src/model/dfcxx/include/dfcxx/channel.h +++ b/src/model/dfcxx/include/dfcxx/channel.h @@ -17,7 +17,8 @@ struct Channel { Node source; Node target; unsigned opInd; - + + Channel() = default; Channel(Node source, Node target, unsigned opInd); bool operator==(const Channel &channel) const; diff --git a/src/model/dfcxx/include/dfcxx/kernel.h b/src/model/dfcxx/include/dfcxx/kernel.h index e43d22d..ce19d63 100644 --- a/src/model/dfcxx/include/dfcxx/kernel.h +++ b/src/model/dfcxx/include/dfcxx/kernel.h @@ -29,9 +29,11 @@ namespace dfcxx { class DFCIRBuilder; +class DFCXXSimulator; class Kernel { friend DFCIRBuilder; + friend DFCXXSimulator; private: KernStorage storage; @@ -68,7 +70,7 @@ class Kernel { const DFOutputPaths &outputPaths, const Scheduler &sched); - bool simulate(const std::vector &data, + bool simulate(const std::vector &dataPaths, std::ostream &stream); }; diff --git a/src/model/dfcxx/include/dfcxx/node.h b/src/model/dfcxx/include/dfcxx/node.h index 1e4e4d2..9c7eb85 100644 --- a/src/model/dfcxx/include/dfcxx/node.h +++ b/src/model/dfcxx/include/dfcxx/node.h @@ -48,7 +48,8 @@ struct Node { DFVariableImpl *var; OpType type; NodeData data; - + + Node() = default; Node(DFVariableImpl *var, OpType type, NodeData data); bool operator==(const Node &node) const; diff --git a/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h b/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h index f22fc2c..c6e2b02 100644 --- a/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h +++ b/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h @@ -17,14 +17,11 @@ #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" -#include - namespace dfcxx { class DFCIRBuilder { private: mlir::MLIRContext ctx; - const DFLatencyConfig &config; mlir::OpBuilder builder; std::unordered_map map; mlir::OwningOpRef module; @@ -37,12 +34,10 @@ class DFCIRBuilder { mlir::ModuleOp buildModule(Kernel *kern, mlir::OpBuilder &builder); - std::stack topSortNodes(Graph *graph); - void translate(Node node, Graph *graph, mlir::OpBuilder &builder); public: - explicit DFCIRBuilder(const DFLatencyConfig &config); + DFCIRBuilder(); mlir::ModuleOp buildModule(Kernel *kern); }; diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h new file mode 100644 index 0000000..4f21de2 --- /dev/null +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// Part of the Utopia HLS Project, under the Apache License v2.0 +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 ISP RAS (http://www.ispras.ru) +// +//===----------------------------------------------------------------------===// + +#ifndef DFCXX_SIMULATOR_H +#define DFCXX_SIMULATOR_H + +#include "dfcxx/kernel.h" + +#include + +namespace dfcxx { + +class DFCXXSimulator { +}; + +} // namespace dfcxx + +#endif // DFCXX_SIMULATOR_H diff --git a/src/model/dfcxx/includeDev/dfcxx/utils.h b/src/model/dfcxx/includeDev/dfcxx/utils.h new file mode 100644 index 0000000..b136b26 --- /dev/null +++ b/src/model/dfcxx/includeDev/dfcxx/utils.h @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// Part of the Utopia HLS Project, under the Apache License v2.0 +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 ISP RAS (http://www.ispras.ru) +// +//===----------------------------------------------------------------------===// + +#ifndef DFCXX_UTILS_H +#define DFCXX_UTILS_H + +#include "dfcxx/graph.h" + +#include +#include +#include +#include + +namespace dfcxx { + +std::vector topSort(std::unordered_set startNodes, + std::unordered_map> outs, + size_t nodesCount); + +} // namespace dfcxx + +#endif // DFCXX_UTILS_H diff --git a/src/model/dfcxx/lib/dfcxx/CMakeLists.txt b/src/model/dfcxx/lib/dfcxx/CMakeLists.txt index a82e35a..7f4ff76 100644 --- a/src/model/dfcxx/lib/dfcxx/CMakeLists.txt +++ b/src/model/dfcxx/lib/dfcxx/CMakeLists.txt @@ -26,6 +26,8 @@ set(SOURCES graph.cpp node.cpp channel.cpp + utils.cpp + simulator.cpp ) add_library(DFCXX STATIC diff --git a/src/model/dfcxx/lib/dfcxx/IRbuilders/CMakeLists.txt b/src/model/dfcxx/lib/dfcxx/IRbuilders/CMakeLists.txt index 8bed545..83b5ac2 100644 --- a/src/model/dfcxx/lib/dfcxx/IRbuilders/CMakeLists.txt +++ b/src/model/dfcxx/lib/dfcxx/IRbuilders/CMakeLists.txt @@ -1,6 +1,5 @@ set(IR_BUILDERS_SOURCES IRbuilders/builder.cpp - IRbuilders/utils.cpp IRbuilders/converter.cpp PARENT_SCOPE ) diff --git a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp index 24a6773..8302d73 100644 --- a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp @@ -7,31 +7,25 @@ //===----------------------------------------------------------------------===// #include "dfcxx/IRbuilders/builder.h" +#include "dfcxx/utils.h" -#include "circt/Dialect/FIRRTL/FIRRTLDialect.h" -#include "circt/Dialect/SV/SVDialect.h" #include "mlir/Parser/Parser.h" namespace dfcxx { -DFCIRBuilder::DFCIRBuilder(const DFLatencyConfig &config) : ctx(), - config(config), - builder(&ctx), - conv(&ctx) { +DFCIRBuilder::DFCIRBuilder() : ctx(), builder(&ctx), conv(&ctx) { // We are allowed to initialize 'builder'-field before loading // dialects as OpBuilder only stores the pointer to MLIRContext // and doesn't check any of its state. ctx.getOrLoadDialect(); - ctx.getOrLoadDialect(); - ctx.getOrLoadDialect(); } void DFCIRBuilder::buildKernelBody(Graph *graph, mlir::OpBuilder &builder) { - std::stack sorted = topSortNodes(graph); + std::vector sorted = topSort(graph->startNodes, + graph->outputs, + graph->nodes.size()); - while (!sorted.empty()) { - Node node = sorted.top(); - sorted.pop(); + for (Node node : sorted) { translate(node, graph, builder); } } @@ -63,4 +57,253 @@ mlir::ModuleOp DFCIRBuilder::buildModule(dfcxx::Kernel *kern) { return module.get(); } +void DFCIRBuilder::translate(dfcxx::Node node, dfcxx::Graph *graph, + mlir::OpBuilder &builder) { + auto loc = builder.getUnknownLoc(); + + const auto &ins = graph->inputs[node]; + + auto nameAttr = mlir::StringAttr::get(&ctx, node.var->getName()); + + switch (node.type) { + case OFFSET: { + Node in = ins[0].source; + auto type = mlir::IntegerType::get(builder.getContext(), 64, + mlir::IntegerType::Signless); + auto attr = mlir::IntegerAttr::get(type, node.data.offset); + auto newOp = builder.create(loc, conv[in.var], + map[in], attr); + map[node] = newOp.getResult(); + break; + } + case IN: { + if (node.var->isStream()) { + auto newOp = builder.create(loc, conv[node.var], + nameAttr, nullptr); + map[node] = newOp.getResult(); + } else { + auto newOp = builder.create(loc, + conv[node.var], + nameAttr); + map[node] = newOp.getResult(); + } + break; + } + case OUT: { + if (node.var->isStream()) { + auto newOp = builder.create(loc, conv[node.var], + nameAttr, nullptr, + nullptr); + map[node] = newOp.getResult(); + } else { + auto newOp = builder.create(loc, + conv[node.var], + nameAttr, + nullptr); + map[node] = newOp.getResult(); + } + break; + } + case CONST: { + auto constant = (DFConstant *) (node.var); + int64_t val; + mlir::IntegerType attrType; + unsigned width = constant->getType().getTotalBits(); + switch (constant->getKind()) { + case INT: + val = constant->getInt(); + attrType = mlir::IntegerType::get(builder.getContext(), width, + mlir::IntegerType::Signed); + break; + case UINT: { + auto tmpU = constant->getUInt(); + memcpy(&val, &tmpU, sizeof(val)); + attrType = mlir::IntegerType::get(builder.getContext(), width, + mlir::IntegerType::Unsigned); + break; + } + case FLOAT: { + auto tmpD = constant->getDouble(); + memcpy(&val, &tmpD, sizeof(val)); + attrType = mlir::IntegerType::get(builder.getContext(), width, + mlir::IntegerType::Signless); + break; + } + } + auto attr = mlir::IntegerAttr::get(attrType, val); + auto newOp = builder.create(loc, conv[node.var], + attr); + map[node] = newOp.getRes(); + break; + } + case MUX: { + Node ctrl = ins[node.data.muxId].source; + llvm::SmallVector mux; + uint64_t size = ins.size(); + for (uint64_t i = 0; i < size; ++i) { + // To produce correct FIRRTL/SystemVerilog code + // multiplexer inputs have to be reversed. + uint64_t ind = size - 1 - i; + if (ind != node.data.muxId) { + mux.push_back(map[ins[ind].source]); + } + } + muxMap[node] = mux; + auto newOp = builder.create(loc, conv[node.var], + map[ctrl], muxMap[node]); + map[node] = newOp.getRes(); + break; + } + case ADD: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], map[second]); + map[node] = newOp.getResult(); + break; + } + case SUB: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], map[second]); + map[node] = newOp.getResult(); + break; + } + case MUL: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], map[second]); + map[node] = newOp.getResult(); + break; + } + case DIV: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], map[second]); + map[node] = newOp.getResult(); + break; + } + case AND: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], map[second]); + map[node] = newOp.getResult(); + break; + } + case OR: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], map[second]); + map[node] = newOp.getResult(); + break; + } + case XOR: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], map[second]); + map[node] = newOp.getResult(); + break; + } + case NOT: { + Node first = ins[0].source; + auto newOp = builder.create(loc, conv[node.var], + map[first]); + map[node] = newOp.getResult(); + break; + } + case NEG: { + Node first = ins[0].source; + auto newOp = builder.create(loc, conv[node.var], + map[first]); + map[node] = newOp.getResult(); + break; + } + case LESS: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], map[second]); + map[node] = newOp.getResult(); + break; + } + case LESSEQ: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); + map[node] = newOp.getResult(); + break; + } + case GREATER: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); + map[node] = newOp.getResult(); + break; + } + case GREATEREQ: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); + map[node] = newOp.getResult(); + break; + } + case EQ: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); + map[node] = newOp.getResult(); + break; + } + case NEQ: { + Node first = ins[0].source; + Node second = ins[1].source; + auto newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); + map[node] = newOp.getResult(); + break; + } + case SHL: { + Node first = ins[0].source; + auto attrType = mlir::IntegerType::get(builder.getContext(), 32, + mlir::IntegerType::Signless); + auto attr = mlir::IntegerAttr::get(attrType, node.data.bitShift); + + auto newOp = builder.create(loc, conv[node.var], + map[first], attr); + map[node] = newOp.getResult(); + break; + } + case SHR: { + Node first = ins[0].source; + auto attrType = mlir::IntegerType::get(builder.getContext(), 32, + mlir::IntegerType::Signless); + auto attr = mlir::IntegerAttr::get(attrType, node.data.bitShift); + + auto newOp = builder.create(loc, conv[node.var], + map[first], attr); + map[node] = newOp.getResult(); + break; + } + } + if (graph->connections.find(node) != graph->connections.end()) { + auto conSrc = graph->connections.at(node).source; + builder.create(loc, map[node], map[conSrc]); + } +} + } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/IRbuilders/utils.cpp b/src/model/dfcxx/lib/dfcxx/IRbuilders/utils.cpp deleted file mode 100644 index 72d0d44..0000000 --- a/src/model/dfcxx/lib/dfcxx/IRbuilders/utils.cpp +++ /dev/null @@ -1,295 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the Utopia HLS Project, under the Apache License v2.0 -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2021-2024 ISP RAS (http://www.ispras.ru) -// -//===----------------------------------------------------------------------===// - -#include "dfcxx/IRbuilders/builder.h" - -namespace dfcxx { - -std::stack DFCIRBuilder::topSortNodes(Graph *graph) { - std::stack result; - - std::unordered_map checked; - std::stack stack; - - for (Node node: graph->startNodes) { - stack.push(node); - checked[node] = 0; - } - - while (!stack.empty()) { - Node node = stack.top(); - size_t count = graph->outputs[node].size(); - size_t curr; - bool flag = true; - for (curr = checked[node]; flag && curr < count; ++curr) { - Channel next = graph->outputs[node][curr]; - if (!checked[next.target]) { - stack.push(next.target); - flag = false; - } - ++checked[node]; - } - - if (flag) { - stack.pop(); - result.push(node); - } - } - return result; -} - -void DFCIRBuilder::translate(dfcxx::Node node, dfcxx::Graph *graph, - mlir::OpBuilder &builder) { - auto loc = builder.getUnknownLoc(); - - const auto &ins = graph->inputs[node]; - - auto nameAttr = mlir::StringAttr::get(&ctx, node.var->getName()); - - switch (node.type) { - case OFFSET: { - Node in = ins[0].source; - auto type = mlir::IntegerType::get(builder.getContext(), 64, - mlir::IntegerType::Signless); - auto attr = mlir::IntegerAttr::get(type, node.data.offset); - auto newOp = builder.create(loc, conv[in.var], - map[in], attr); - map[node] = newOp.getResult(); - break; - } - case IN: { - if (node.var->isStream()) { - auto newOp = builder.create(loc, conv[node.var], - nameAttr, nullptr); - map[node] = newOp.getResult(); - } else { - auto newOp = builder.create(loc, - conv[node.var], - nameAttr); - map[node] = newOp.getResult(); - } - break; - } - case OUT: { - if (node.var->isStream()) { - auto newOp = builder.create(loc, conv[node.var], - nameAttr, nullptr, - nullptr); - map[node] = newOp.getResult(); - } else { - auto newOp = builder.create(loc, - conv[node.var], - nameAttr, - nullptr); - map[node] = newOp.getResult(); - } - break; - } - case CONST: { - auto constant = (DFConstant *) (node.var); - int64_t val; - mlir::IntegerType attrType; - unsigned width = constant->getType().getTotalBits(); - switch (constant->getKind()) { - case INT: - val = constant->getInt(); - attrType = mlir::IntegerType::get(builder.getContext(), width, - mlir::IntegerType::Signed); - break; - case UINT: { - auto tmpU = constant->getUInt(); - memcpy(&val, &tmpU, sizeof(val)); - attrType = mlir::IntegerType::get(builder.getContext(), width, - mlir::IntegerType::Unsigned); - break; - } - case FLOAT: { - auto tmpD = constant->getDouble(); - memcpy(&val, &tmpD, sizeof(val)); - attrType = mlir::IntegerType::get(builder.getContext(), width, - mlir::IntegerType::Signless); - break; - } - } - auto attr = mlir::IntegerAttr::get(attrType, val); - auto newOp = builder.create(loc, conv[node.var], - attr); - map[node] = newOp.getRes(); - break; - } - case MUX: { - Node ctrl = ins[node.data.muxId].source; - llvm::SmallVector mux; - uint64_t size = ins.size(); - for (uint64_t i = 0; i < size; ++i) { - // To produce correct FIRRTL/SystemVerilog code - // multiplexer inputs have to be reversed. - uint64_t ind = size - 1 - i; - if (ind != node.data.muxId) { - mux.push_back(map[ins[ind].source]); - } - } - muxMap[node] = mux; - auto newOp = builder.create(loc, conv[node.var], - map[ctrl], muxMap[node]); - map[node] = newOp.getRes(); - break; - } - case ADD: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); - break; - } - case SUB: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); - break; - } - case MUL: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); - break; - } - case DIV: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); - break; - } - case AND: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); - break; - } - case OR: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); - break; - } - case XOR: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); - break; - } - case NOT: { - Node first = ins[0].source; - auto newOp = builder.create(loc, conv[node.var], - map[first]); - map[node] = newOp.getResult(); - break; - } - case NEG: { - Node first = ins[0].source; - auto newOp = builder.create(loc, conv[node.var], - map[first]); - map[node] = newOp.getResult(); - break; - } - case LESS: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); - break; - } - case LESSEQ: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); - break; - } - case GREATER: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); - break; - } - case GREATEREQ: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); - break; - } - case EQ: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); - break; - } - case NEQ: { - Node first = ins[0].source; - Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); - break; - } - case SHL: { - Node first = ins[0].source; - auto attrType = mlir::IntegerType::get(builder.getContext(), 32, - mlir::IntegerType::Signless); - auto attr = mlir::IntegerAttr::get(attrType, node.data.bitShift); - - auto newOp = builder.create(loc, conv[node.var], - map[first], attr); - map[node] = newOp.getResult(); - break; - } - case SHR: { - Node first = ins[0].source; - auto attrType = mlir::IntegerType::get(builder.getContext(), 32, - mlir::IntegerType::Signless); - auto attr = mlir::IntegerAttr::get(attrType, node.data.bitShift); - - auto newOp = builder.create(loc, conv[node.var], - map[first], attr); - map[node] = newOp.getResult(); - break; - } - } - if (graph->connections.find(node) != graph->connections.end()) { - auto conSrc = graph->connections.at(node).source; - builder.create(loc, map[node], map[conSrc]); - } -} - -} // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/converter.cpp b/src/model/dfcxx/lib/dfcxx/converter.cpp index 714a8e2..73fbfc4 100644 --- a/src/model/dfcxx/lib/dfcxx/converter.cpp +++ b/src/model/dfcxx/lib/dfcxx/converter.cpp @@ -9,6 +9,8 @@ #include "dfcxx/converter.h" #include "circt/Conversion/Passes.h" +#include "circt/Dialect/FIRRTL/FIRRTLDialect.h" +#include "circt/Dialect/SV/SVDialect.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" @@ -51,6 +53,8 @@ bool DFCIRConverter::convertAndPrint(mlir::ModuleOp module, OutputStreams &outputStreams, const Scheduler &sched) { mlir::MLIRContext *context = module.getContext(); + context->getOrLoadDialect(); + context->getOrLoadDialect(); mlir::PassManager pm(context); // Dump DFCIR if the corresponding option is specified. diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index 8345758..dbf64bb 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -9,6 +9,7 @@ #include "dfcxx/converter.h" #include "dfcxx/IRbuilders/builder.h" #include "dfcxx/kernel.h" +#include "dfcxx/utils.h" #include @@ -44,7 +45,7 @@ DFType Kernel::dfBool() { bool Kernel::compile(const DFLatencyConfig &config, const std::vector &outputPaths, const Scheduler &sched) { - DFCIRBuilder builder(config); + DFCIRBuilder builder; auto compiled = builder.buildModule(this); size_t count = outputPaths.size(); std::vector outputStreams(count); @@ -78,9 +79,15 @@ bool Kernel::compile(const DFLatencyConfig &config, return compile(config, outPathsStrings, sched); } -bool Kernel::simulate(const std::vector &data, + +bool Kernel::simulate(const std::vector &dataPaths, std::ostream &stream) { - return true; + bool result = true; + std::vector sorted = topSort(graph.startNodes, + graph.outputs, + graph.nodes.size()); + + return result; } } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp new file mode 100644 index 0000000..6a0f17d --- /dev/null +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -0,0 +1,5 @@ +#include "dfcxx/simulator.h" + +namespace dfcxx { + +} // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/utils.cpp b/src/model/dfcxx/lib/dfcxx/utils.cpp new file mode 100644 index 0000000..329f41c --- /dev/null +++ b/src/model/dfcxx/lib/dfcxx/utils.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// Part of the Utopia HLS Project, under the Apache License v2.0 +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 ISP RAS (http://www.ispras.ru) +// +//===----------------------------------------------------------------------===// + +#include "dfcxx/utils.h" + +namespace dfcxx { + +std::vector topSort(std::unordered_set startNodes, + std::unordered_map> outs, + size_t nodesCount) { + std::vector result(nodesCount); + + std::unordered_map checked; + std::stack stack; + + for (Node node: startNodes) { + stack.push(node); + checked[node] = 0; + } + + size_t i = nodesCount - 1; + while (!stack.empty()) { + Node node = stack.top(); + size_t count = outs[node].size(); + size_t curr; + bool flag = true; + for (curr = checked[node]; flag && curr < count; ++curr) { + Channel next = outs[node][curr]; + if (!checked[next.target]) { + stack.push(next.target); + flag = false; + } + ++checked[node]; + } + + if (flag) { + stack.pop(); + result[i--] = node; + } + } + return result; +} + +} // namespace dfcxx From 5aabc77d1826252c0190a9b8bd970086c10e5d1f Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Fri, 16 Aug 2024 23:01:43 +0300 Subject: [PATCH 04/21] Various struct/classes/enum declarations for simulator were added. --- src/model/dfcxx/includeDev/dfcxx/simulator.h | 40 +++++++++++++++++++- src/model/dfcxx/lib/dfcxx/kernel.cpp | 9 ++++- src/model/dfcxx/lib/dfcxx/simulator.cpp | 8 ++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index 4f21de2..d81fa4a 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -9,13 +9,51 @@ #ifndef DFCXX_SIMULATOR_H #define DFCXX_SIMULATOR_H -#include "dfcxx/kernel.h" +#include "dfcxx/graph.h" +#include +#include +#include #include namespace dfcxx { +union SimValue { + int64_t int_; + uint64_t uint_; + double double_; +}; + +enum class SimType : uint8_t { + INT = 0, + UINT, + FLOAT +}; + +struct SimVariable { + std::string name; + SimType type; + + SimVariable(std::string name, SimType type) : name(name), type(type) {} +}; + +} // namespace dfcxx + +template <> +struct std::hash { + size_t operator()(const dfcxx::SimVariable &var) const noexcept { + return std::hash()(var.name); + } +}; + +typedef std::unordered_map> SimVars; + +namespace dfcxx { + class DFCXXSimulator { +public: + bool simulate(std::ifstream &in, std::ostream &out, std::vector nodes); }; } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index dbf64bb..7198c37 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -9,8 +9,10 @@ #include "dfcxx/converter.h" #include "dfcxx/IRbuilders/builder.h" #include "dfcxx/kernel.h" +#include "dfcxx/simulator.h" #include "dfcxx/utils.h" +#include #include namespace dfcxx { @@ -86,7 +88,12 @@ bool Kernel::simulate(const std::vector &dataPaths, std::vector sorted = topSort(graph.startNodes, graph.outputs, graph.nodes.size()); - + DFCXXSimulator sim; + for (const std::string &path : dataPaths) { + std::ifstream input(path, std::ios::in); + sim.simulate(input, stream, sorted); + } + return result; } diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 6a0f17d..0b1b9a7 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -2,4 +2,12 @@ namespace dfcxx { + + +bool DFCXXSimulator::simulate(std::ifstream &in, + std::ostream &out, + std::vector nodes) { + return true; +} + } // namespace dfcxx From 4ebe4501fcca571c9eead24e34f19cc4398c1e67 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Sat, 17 Aug 2024 01:22:09 +0300 Subject: [PATCH 05/21] Simulation output path option was added. --- src/main.cpp | 3 ++- src/model/dfcxx/include/dfcxx/kernel.h | 2 +- src/model/dfcxx/includeDev/dfcxx/simulator.h | 2 +- src/model/dfcxx/lib/dfcxx/kernel.cpp | 5 +++-- src/model/dfcxx/lib/dfcxx/simulator.cpp | 2 +- src/options.h | 13 +++++++++++++ 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 796abc2..5bf925e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -53,7 +53,8 @@ int hlsMain(const HlsContext &context) { int simMain(const SimContext &context) { auto kernel = start(); - return !kernel->simulate(context.options.dataFiles(), std::cout); + return !kernel->simulate(context.options.dataFiles(), + context.options.outFilePath); } int main(int argc, char **argv) { diff --git a/src/model/dfcxx/include/dfcxx/kernel.h b/src/model/dfcxx/include/dfcxx/kernel.h index ce19d63..64b1071 100644 --- a/src/model/dfcxx/include/dfcxx/kernel.h +++ b/src/model/dfcxx/include/dfcxx/kernel.h @@ -71,7 +71,7 @@ class Kernel { const Scheduler &sched); bool simulate(const std::vector &dataPaths, - std::ostream &stream); + const std::string &outFilePath); }; diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index d81fa4a..eeb7aa9 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -53,7 +53,7 @@ namespace dfcxx { class DFCXXSimulator { public: - bool simulate(std::ifstream &in, std::ostream &out, std::vector nodes); + bool simulate(std::ifstream &in, std::ofstream &out, std::vector nodes); }; } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index 7198c37..d417095 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -83,15 +83,16 @@ bool Kernel::compile(const DFLatencyConfig &config, bool Kernel::simulate(const std::vector &dataPaths, - std::ostream &stream) { + const std::string &outFilePath) { bool result = true; std::vector sorted = topSort(graph.startNodes, graph.outputs, graph.nodes.size()); DFCXXSimulator sim; + std::ofstream out(outFilePath, std::ios::out); for (const std::string &path : dataPaths) { std::ifstream input(path, std::ios::in); - sim.simulate(input, stream, sorted); + sim.simulate(input, out, sorted); } return result; diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 0b1b9a7..965dd97 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -5,7 +5,7 @@ namespace dfcxx { bool DFCXXSimulator::simulate(std::ifstream &in, - std::ostream &out, + std::ofstream &out, std::vector nodes) { return true; } diff --git a/src/options.h b/src/options.h index ad67e79..25cd6f9 100644 --- a/src/options.h +++ b/src/options.h @@ -42,6 +42,7 @@ #define OUT_FIRRTL_JSON "out_firrtl" #define SIM_ID_JSON "sim" +#define SIM_OUT_JSON "out" //===----------------------------------------------------------------------===// // CLI args/flags definitions @@ -59,6 +60,7 @@ #define OUT_FIRRTL_ARG CLI_ARG("out-firrtl") #define SIM_USAGE_FILES_ARG "files" +#define SIM_OUT_ARG CLI_ARG("out") //===----------------------------------------------------------------------===// @@ -319,6 +321,11 @@ struct SimOptions final : public AppOptions { SimOptions(AppOptions &parent): AppOptions(parent, SIM_CMD, "DFCxx simulation") { //options->formatter(std::make_shared()); + + // Named options. + options->add_option(SIM_OUT_ARG, + outFilePath, + "Simulation output path")->expected(1); // For processing data files' paths. options->allow_extras(); auto *var = options; // Used for lambda variable passing. @@ -332,6 +339,12 @@ struct SimOptions final : public AppOptions { std::vector dataFiles() const { return options->remaining(); } + + void fromJson(Json json) override { + get(json, SIM_OUT_JSON, outFilePath); + } + + std::string outFilePath; }; struct Options final : public AppOptions { From 8a0fe36a21126bc73f9ac647915262e6d0a8d9be Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Mon, 19 Aug 2024 20:08:37 +0300 Subject: [PATCH 06/21] Additional (not finished) simulation logic was added. --- src/model/dfcxx/include/dfcxx/kernel.h | 2 - src/model/dfcxx/include/dfcxx/vars/constant.h | 12 +- src/model/dfcxx/includeDev/dfcxx/simulator.h | 60 ++++----- src/model/dfcxx/lib/dfcxx/kernel.cpp | 4 +- src/model/dfcxx/lib/dfcxx/simulator.cpp | 123 +++++++++++++++++- 5 files changed, 160 insertions(+), 41 deletions(-) diff --git a/src/model/dfcxx/include/dfcxx/kernel.h b/src/model/dfcxx/include/dfcxx/kernel.h index 64b1071..b5b4586 100644 --- a/src/model/dfcxx/include/dfcxx/kernel.h +++ b/src/model/dfcxx/include/dfcxx/kernel.h @@ -29,11 +29,9 @@ namespace dfcxx { class DFCIRBuilder; -class DFCXXSimulator; class Kernel { friend DFCIRBuilder; - friend DFCXXSimulator; private: KernStorage storage; diff --git a/src/model/dfcxx/include/dfcxx/vars/constant.h b/src/model/dfcxx/include/dfcxx/vars/constant.h index 4d06198..c2a1080 100644 --- a/src/model/dfcxx/include/dfcxx/vars/constant.h +++ b/src/model/dfcxx/include/dfcxx/vars/constant.h @@ -42,6 +42,12 @@ class DFConstant : DFVariableImpl { public: ~DFConstant() override = default; + + int64_t getInt() const; + + uint64_t getUInt() const; + + double getDouble() const; protected: DFTypeImpl &getType() override; @@ -82,12 +88,6 @@ class DFConstant : DFVariableImpl { ConstantTypeKind getKind() const; - int64_t getInt() const; - - uint64_t getUInt() const; - - double getDouble() const; - bool isConstant() const override; }; diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index eeb7aa9..04a3c19 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -11,6 +11,7 @@ #include "dfcxx/graph.h" +#include #include #include #include @@ -18,42 +19,43 @@ namespace dfcxx { -union SimValue { - int64_t int_; - uint64_t uint_; - double double_; -}; +typedef uint64_t SimValue; -enum class SimType : uint8_t { - INT = 0, - UINT, - FLOAT -}; +// Buffer size for reading from and writing to simulation data files. +#define BUF_SIZE 200 -struct SimVariable { - std::string name; - SimType type; +typedef std::unordered_map> SimVars; - SimVariable(std::string name, SimType type) : name(name), type(type) {} -}; - -} // namespace dfcxx +typedef std::unordered_map> Inputs; -template <> -struct std::hash { - size_t operator()(const dfcxx::SimVariable &var) const noexcept { - return std::hash()(var.name); - } -}; - -typedef std::unordered_map> SimVars; - -namespace dfcxx { +typedef std::unordered_map RecordedValues; class DFCXXSimulator { public: - bool simulate(std::ifstream &in, std::ofstream &out, std::vector nodes); + DFCXXSimulator(std::vector &nodes, + Inputs &inputs); + bool simulate(std::ifstream &in, std::ofstream &out); + +private: + uint64_t readInputData(std::ifstream &in, SimVars &inputMapping); + bool runSim(SimVars &input, SimVars &output, uint64_t count); + bool writeOutput(std::ofstream &out, SimVars &output, uint64_t count); + + void processInput(RecordedValues &vals, Node &node, + SimVars &input, uint64_t ind); + void processOutput(RecordedValues &vals, Node &node, + SimVars &output, uint64_t ind); + void processConst(RecordedValues &vals, Node &node); + void processMux(RecordedValues &vals, Node &node); + template + void processBinaryOp(RecordedValues &vals, Node &node); + template + void processUnaryOp(RecordedValues &vals, Node &node); + void processShiftLeft(RecordedValues &vals, Node &node); + void processShiftRight(RecordedValues &vals, Node &node); + std::vector &nodes; + Inputs &inputs; }; } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index d417095..93c0ec4 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -88,11 +88,11 @@ bool Kernel::simulate(const std::vector &dataPaths, std::vector sorted = topSort(graph.startNodes, graph.outputs, graph.nodes.size()); - DFCXXSimulator sim; + DFCXXSimulator sim(sorted, graph.inputs); std::ofstream out(outFilePath, std::ios::out); for (const std::string &path : dataPaths) { std::ifstream input(path, std::ios::in); - sim.simulate(input, out, sorted); + sim.simulate(input, out); } return result; diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 965dd97..1baec0c 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -1,12 +1,131 @@ #include "dfcxx/simulator.h" +#include "dfcxx/vars/vars.h" + +#include + namespace dfcxx { +DFCXXSimulator::DFCXXSimulator(std::vector &nodes, + Inputs &inputs) : nodes(nodes), + inputs(inputs) {} + + + +uint64_t DFCXXSimulator::readInputData(std::ifstream &in, + SimVars &inputMapping) { + uint64_t ind = 0; + std::string line; + while (std::getline(in, line) && ind < BUF_SIZE) { + // An empty line is treated as a data block delimiter. + if (line.empty()) { + ++ind; + continue; + } + size_t spaceInd = line.find(' '); + if (spaceInd == line.npos || + spaceInd == 0 || + spaceInd == line.size() - 1) { + return 0; + } + inputMapping[line.substr(0, spaceInd)][ind] = + std::stoul(line.substr(spaceInd + 1), 0, 16); + } + // It is assumed that at least one data block exists. + return ind + 1; +} + +void DFCXXSimulator::processInput(RecordedValues &vals, Node &node, + SimVars &input, uint64_t ind) { + auto name = std::string(DFVariable(node.var).getName()); + vals[node] = input[name][ind]; +} + +void DFCXXSimulator::processOutput(RecordedValues &vals, Node &node, + SimVars &output, uint64_t ind) { + auto name = std::string(DFVariable(node.var).getName()); + // Take output's only connection and assign the existing source value. + vals[node] = vals[inputs[node][0].source]; + output[name][ind] = vals[node]; +} +void DFCXXSimulator::processConst(RecordedValues &vals, Node &node) { + vals[node] = ((DFConstant *) node.var)->getUInt(); +} + +void DFCXXSimulator::processMux(RecordedValues &vals, Node &node) { + auto muxedValue = vals[inputs[node][node.data.muxId].source]; + vals[node] = vals[inputs[node][muxedValue].source]; +} + +bool DFCXXSimulator::runSim(SimVars &input, + SimVars &output, + uint64_t count) { + // Node->value mapping is initialized. This allows us + // to rememeber the relevant value for the operand node. + // With every single "clock" (loop iteration) input + // nodes' mapping is updated with the value from the buffer. + RecordedValues vals; + for (uint64_t i = 0; i < count; ++i) { + for (Node &node : nodes) { + switch (node.type) { + case OFFSET: + return false; // TODO: Add offset support in the future. + case IN: processInput(vals, node, input, i); break; + case OUT: processOutput(vals, node, output, i); break; + case CONST: processConst(vals, node); break; + case MUX: processMux(vals, node); break; + //case ADD: processBinaryOp(vals, node); break; + //case SUB: processBinaryOp(vals, node); break; + //case MUL: processBinaryOp(vals, node); break; + //case DIV: processBinaryOp(vals, node); break; + //case AND: processBinaryOp(vals, node); break; + //case OR: processBinaryOp(vals, node); break; + //case XOR: processBinaryOp(vals, node); break; + //case NOT: processUnaryOp(vals, node); break; + //case NEG: processUnaryOp(vals, node); break; + //case LESS: processBinaryOp(vals, node); break; + //case LESSEQ: processBinaryOp(vals, node); break; + //case GREATER: processBinaryOp(vals, node); break; + //case GREATEREQ: processBinaryOp(vals, node); break; + //case EQ: processBinaryOp(vals, node); break; + //case NEQ: processBinaryOp(vals, node); break; + //case SHL: processShiftLeft(vals, node); break; + //case SHR: processShiftRight(vals, node); break; + } + } + } + return true; +} + +bool DFCXXSimulator::writeOutput(std::ofstream &out, + SimVars &output, + uint64_t count) { + auto outFunc = [&out, &output] (uint64_t iter) { + for (auto &kv : output) { + out << kv.first << " " << std::to_string(kv.second[iter]) << "\n"; + } + }; + + outFunc(0); + for (uint64_t i = 1; i < count; ++i) { + out << "\n"; + outFunc(i); + } +} bool DFCXXSimulator::simulate(std::ifstream &in, - std::ofstream &out, - std::vector nodes) { + std::ofstream &out) { + SimVars input; + SimVars output; + while (uint64_t count = readInputData(in, input)) { + // If either the simulation itself or writing to output file + // fails - return false. + if (!runSim(input, output, count) || + !writeOutput(out, output, count)) { + return false; + } + } return true; } From 29dac55885c04b5fe08067553504fd24a32a1312 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Mon, 19 Aug 2024 22:47:04 +0300 Subject: [PATCH 07/21] Additional simulation logic added (incomplete). --- src/main.cpp | 3 - src/model/dfcxx/lib/dfcxx/simulator.cpp | 317 ++++++++++++++++++++++-- 2 files changed, 299 insertions(+), 21 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5bf925e..bdd36a8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -82,7 +82,4 @@ int main(int argc, char **argv) { } else { return simMain(SimContext(options.sim)); } - - HlsContext context(options.hls); - return hlsMain(context); } diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 1baec0c..7448314 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -1,5 +1,5 @@ #include "dfcxx/simulator.h" - +#include "dfcxx/types/types.h" #include "dfcxx/vars/vars.h" #include @@ -58,6 +58,286 @@ void DFCXXSimulator::processMux(RecordedValues &vals, Node &node) { vals[node] = vals[inputs[node][muxedValue].source]; } +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left + right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] + vals[inputs[node][1].source]; + } + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double result = left + right; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left - right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] - vals[inputs[node][1].source]; + } + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double result = left - right; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left * right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] * vals[inputs[node][1].source]; + } + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double result = left * right; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left / right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] / vals[inputs[node][1].source]; + } + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double result = left / right; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left & right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] & vals[inputs[node][1].source]; + } + } + // No AND for floats. +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left | right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] | vals[inputs[node][1].source]; + } + } + // No OR for floats. +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left ^ right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] ^ vals[inputs[node][1].source]; + } + } + // No XOR for floats. +} + +template <> +void DFCXXSimulator::processUnaryOp(RecordedValues &vals, + Node &node) { + vals[node] = ~(vals[inputs[node][0].source]); +} + +template <> +void DFCXXSimulator::processUnaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t result = -left; + vals[node] = *(reinterpret_cast(&result)); + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double result = -left; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left < right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] < vals[inputs[node][1].source]; + } + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double result = left < right; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left <= right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] <= vals[inputs[node][1].source]; + } + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double result = left <= right; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left > right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] > vals[inputs[node][1].source]; + } + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double result = left > right; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t result = left >= right; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] >= vals[inputs[node][1].source]; + } + } else { + double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double result = left >= right; + vals[node] = *(reinterpret_cast(&result)); + } +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + vals[node] = vals[inputs[node][0].source] == vals[inputs[node][1].source]; +} + +template <> +void DFCXXSimulator::processBinaryOp(RecordedValues &vals, + Node &node) { + vals[node] = vals[inputs[node][0].source] != vals[inputs[node][1].source]; +} + +void DFCXXSimulator::processShiftLeft(RecordedValues &vals, Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t result = left << node.data.bitShift; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] << node.data.bitShift; + } + } + // No left bit shift for floats. +} + +void DFCXXSimulator::processShiftRight(RecordedValues &vals, Node &node) { + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); + if (type->isFixed()) { + if (((FixedType*) type)->isSigned()) { + int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t result = left >> node.data.bitShift; + vals[node] = *(reinterpret_cast(&result)); + } else { + vals[node] = vals[inputs[node][0].source] >> node.data.bitShift; + } + } + // No right bit shift for floats. +} + bool DFCXXSimulator::runSim(SimVars &input, SimVars &output, uint64_t count) { @@ -75,23 +355,23 @@ bool DFCXXSimulator::runSim(SimVars &input, case OUT: processOutput(vals, node, output, i); break; case CONST: processConst(vals, node); break; case MUX: processMux(vals, node); break; - //case ADD: processBinaryOp(vals, node); break; - //case SUB: processBinaryOp(vals, node); break; - //case MUL: processBinaryOp(vals, node); break; - //case DIV: processBinaryOp(vals, node); break; - //case AND: processBinaryOp(vals, node); break; - //case OR: processBinaryOp(vals, node); break; - //case XOR: processBinaryOp(vals, node); break; - //case NOT: processUnaryOp(vals, node); break; - //case NEG: processUnaryOp(vals, node); break; - //case LESS: processBinaryOp(vals, node); break; - //case LESSEQ: processBinaryOp(vals, node); break; - //case GREATER: processBinaryOp(vals, node); break; - //case GREATEREQ: processBinaryOp(vals, node); break; - //case EQ: processBinaryOp(vals, node); break; - //case NEQ: processBinaryOp(vals, node); break; - //case SHL: processShiftLeft(vals, node); break; - //case SHR: processShiftRight(vals, node); break; + case ADD: processBinaryOp(vals, node); break; + case SUB: processBinaryOp(vals, node); break; + case MUL: processBinaryOp(vals, node); break; + case DIV: processBinaryOp(vals, node); break; + case AND: processBinaryOp(vals, node); break; + case OR: processBinaryOp(vals, node); break; + case XOR: processBinaryOp(vals, node); break; + case NOT: processUnaryOp(vals, node); break; + case NEG: processUnaryOp(vals, node); break; + case LESS: processBinaryOp(vals, node); break; + case LESSEQ: processBinaryOp(vals, node); break; + case GREATER: processBinaryOp(vals, node); break; + case GREATEREQ: processBinaryOp(vals, node); break; + case EQ: processBinaryOp(vals, node); break; + case NEQ: processBinaryOp(vals, node); break; + case SHL: processShiftLeft(vals, node); break; + case SHR: processShiftRight(vals, node); break; } } } @@ -112,6 +392,7 @@ bool DFCXXSimulator::writeOutput(std::ofstream &out, out << "\n"; outFunc(i); } + return true; } bool DFCXXSimulator::simulate(std::ifstream &in, From 6e0e75079b4b7f1b6e45ed7d35e3f9e6aa383d05 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Tue, 20 Aug 2024 01:24:22 +0300 Subject: [PATCH 08/21] Minor simulation logic fixes; added simulation input data examples. --- examples/addconst/sim.txt | 5 +++++ examples/matrixmul2/sim.txt | 8 ++++++++ examples/muxmul/sim.txt | 8 ++++++++ examples/polynomial2/sim.txt | 5 +++++ examples/scalar3/sim.txt | 6 ++++++ src/model/dfcxx/lib/dfcxx/simulator.cpp | 8 +++++--- src/options.h | 21 +++++++++++++-------- 7 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 examples/addconst/sim.txt create mode 100644 examples/matrixmul2/sim.txt create mode 100644 examples/muxmul/sim.txt create mode 100644 examples/polynomial2/sim.txt create mode 100644 examples/scalar3/sim.txt diff --git a/examples/addconst/sim.txt b/examples/addconst/sim.txt new file mode 100644 index 0000000..1e7620b --- /dev/null +++ b/examples/addconst/sim.txt @@ -0,0 +1,5 @@ +x 0x32 + +x 0x45 + +x 0x56 diff --git a/examples/matrixmul2/sim.txt b/examples/matrixmul2/sim.txt new file mode 100644 index 0000000..0c3a5fa --- /dev/null +++ b/examples/matrixmul2/sim.txt @@ -0,0 +1,8 @@ +x11 0x32 +x12 0x64 +x21 0x48 +x22 0x99 +y11 0x1 +y12 0x0 +y21 0x0 +y22 0x1 diff --git a/examples/muxmul/sim.txt b/examples/muxmul/sim.txt new file mode 100644 index 0000000..4edb971 --- /dev/null +++ b/examples/muxmul/sim.txt @@ -0,0 +1,8 @@ +x 0x32 +ctrl 0x1 + +x 0x45 +ctrl 0x0 + +x 0x56 +ctrl 0x1 diff --git a/examples/polynomial2/sim.txt b/examples/polynomial2/sim.txt new file mode 100644 index 0000000..1e7620b --- /dev/null +++ b/examples/polynomial2/sim.txt @@ -0,0 +1,5 @@ +x 0x32 + +x 0x45 + +x 0x56 diff --git a/examples/scalar3/sim.txt b/examples/scalar3/sim.txt new file mode 100644 index 0000000..db2cb18 --- /dev/null +++ b/examples/scalar3/sim.txt @@ -0,0 +1,6 @@ +x1 0x2 +y1 0x32 +x2 0x3 +y2 0x32 +x3 0x4 +y3 0x32 \ No newline at end of file diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 7448314..93bc757 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -16,6 +16,7 @@ uint64_t DFCXXSimulator::readInputData(std::ifstream &in, SimVars &inputMapping) { uint64_t ind = 0; std::string line; + bool atLeastOne = false; while (std::getline(in, line) && ind < BUF_SIZE) { // An empty line is treated as a data block delimiter. if (line.empty()) { @@ -28,11 +29,12 @@ uint64_t DFCXXSimulator::readInputData(std::ifstream &in, spaceInd == line.size() - 1) { return 0; } + atLeastOne = true; inputMapping[line.substr(0, spaceInd)][ind] = std::stoul(line.substr(spaceInd + 1), 0, 16); } // It is assumed that at least one data block exists. - return ind + 1; + return atLeastOne ? (ind + 1) : 0; } void DFCXXSimulator::processInput(RecordedValues &vals, Node &node, @@ -55,7 +57,7 @@ void DFCXXSimulator::processConst(RecordedValues &vals, Node &node) { void DFCXXSimulator::processMux(RecordedValues &vals, Node &node) { auto muxedValue = vals[inputs[node][node.data.muxId].source]; - vals[node] = vals[inputs[node][muxedValue].source]; + vals[node] = vals[inputs[node][muxedValue + 1].source]; } template <> @@ -383,7 +385,7 @@ bool DFCXXSimulator::writeOutput(std::ofstream &out, uint64_t count) { auto outFunc = [&out, &output] (uint64_t iter) { for (auto &kv : output) { - out << kv.first << " " << std::to_string(kv.second[iter]) << "\n"; + out << kv.first << " 0x" << std::hex << kv.second[iter] << "\n"; } }; diff --git a/src/options.h b/src/options.h index 25cd6f9..dea8fab 100644 --- a/src/options.h +++ b/src/options.h @@ -61,6 +61,7 @@ #define SIM_USAGE_FILES_ARG "files" #define SIM_OUT_ARG CLI_ARG("out") +#define SIM_FILES_ARG CLI_ARG("files") //===----------------------------------------------------------------------===// @@ -326,18 +327,21 @@ struct SimOptions final : public AppOptions { options->add_option(SIM_OUT_ARG, outFilePath, "Simulation output path")->expected(1); + options->add_option(SIM_FILES_ARG, + files, + "Simulation output path"); // For processing data files' paths. - options->allow_extras(); - auto *var = options; // Used for lambda variable passing. - options->callback([&var]() { - if (var->remaining_size() < 1) { - throw CLI::ArgumentMismatch("input data files", -1, 0); - } - }); + // options->allow_extras(); + // auto *var = options; // Used for lambda variable passing. + // options->callback([&var]() { + // if (var->remaining_size() < 1) { + // throw CLI::ArgumentMismatch("input data files", -1, 0); + // } + // }); } std::vector dataFiles() const { - return options->remaining(); + return files; } void fromJson(Json json) override { @@ -345,6 +349,7 @@ struct SimOptions final : public AppOptions { } std::string outFilePath; + std::vector files; }; struct Options final : public AppOptions { From 58b7a0dc2f6b8ec1ee355b9659b399317e12004e Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Tue, 20 Aug 2024 16:44:04 +0300 Subject: [PATCH 09/21] SimVars -> IOVars; IDCT example simulation input data was added; IDCT example minor fixes. --- examples/idct/idct.h | 33 +++++----- examples/idct/sim.txt | 64 ++++++++++++++++++++ src/model/dfcxx/includeDev/dfcxx/simulator.h | 14 ++--- src/model/dfcxx/lib/dfcxx/simulator.cpp | 16 ++--- 4 files changed, 97 insertions(+), 30 deletions(-) create mode 100644 examples/idct/sim.txt diff --git a/examples/idct/idct.h b/examples/idct/idct.h index 56ad875..e1ba5e1 100644 --- a/examples/idct/idct.h +++ b/examples/idct/idct.h @@ -29,6 +29,9 @@ class IDCT : public dfcxx::Kernel { DFVariable const8192 = constant.var(type, int64_t(8192)); DFVariable const4 = constant.var(type, int64_t(4)); + DFVariable constM256 = constant.var(type, int64_t(-256)); + DFVariable const255 = constant.var(type, int64_t(255)); + DFVariable W1 = constant.var(type, int64_t(2841)); DFVariable W2 = constant.var(type, int64_t(2676)); DFVariable W3 = constant.var(type, int64_t(2408)); @@ -53,17 +56,17 @@ class IDCT : public dfcxx::Kernel { DFVariable x7 = (values[kDIM * i + 3]); DFVariable x8 = (x4 + x5) * W7; - x4 = x8 + (W1 - W7) * x4; - x5 = x8 - (W1 - W7) * x5; - x8 = W3 * (x6 + x7); - x6 = x8 - (W3 - W5) * x6; - x7 = x8 - (W3 + W5) * x7; + x4 = x8 + x4 * (W1 - W7); + x5 = x8 - x5 * (W1 + W7); + x8 = (x6 + x7) * W3; + x6 = x8 - x6 * (W3 - W5); + x7 = x8 - x7 * (W3 + W5); x8 = x0 + x1; x0 = x0 - x1; x1 = (x3 + x2) * W6; - x2 = x1 - (W2 + W6) * x2; - x3 = x1 + (W2 - W6) * x3; + x2 = x1 - x2 * (W2 + W6); + x3 = x1 + x3 * (W2 - W6); x1 = x4 + x6; x4 = x4 - x6; x6 = x5 + x7; @@ -97,17 +100,17 @@ class IDCT : public dfcxx::Kernel { DFVariable x7 = values[kDIM * 3 + i]; DFVariable x8 = ((x4 + x5) * W7) + const4; - x4 = (x8 + (W1 - W7) * x4) >> 3; - x5 = (x8 - (W1 - W7) * x5) >> 3; - x8 = (W3 * (x6 + x7)) + const4; - x6 = (x8 - (W3 - W5) * x6) >> 3; - x7 = (x8 - (W3 + W5) * x7) >> 3; + x4 = (x8 + x4 * (W1 - W7)) >> 3; + x5 = (x8 - x5 * (W1 + W7)) >> 3; + x8 = ((x6 + x7) * W3) + const4; + x6 = (x8 - x6 * (W3 - W5)) >> 3; + x7 = (x8 - x7 * (W3 + W5)) >> 3; x8 = x0 + x1; x0 = x0 - x1; x1 = ((x3 + x2) * W6) + const4; - x2 = (x1 - (W2 + W6) * x2) >> 3; - x3 = (x1 + (W2 - W6) * x3) >> 3; + x2 = (x1 - x2 * (W2 + W6)) >> 3; + x3 = (x1 + x3 * (W2 - W6)) >> 3; x1 = x4 + x6; x4 = x4 - x6; x6 = x5 + x7; @@ -119,7 +122,7 @@ class IDCT : public dfcxx::Kernel { x0 = x0 - x2; x2 = (((x4 + x5) * const181) + const128) >> 8; x4 = (((x4 - x5) * const181) + const128) >> 8; - + values[kDIM * 0 + i] = (x7 + x1) >> 14; values[kDIM * 1 + i] = (x3 + x2) >> 14; values[kDIM * 2 + i] = (x0 + x4) >> 14; diff --git a/examples/idct/sim.txt b/examples/idct/sim.txt new file mode 100644 index 0000000..339e8fd --- /dev/null +++ b/examples/idct/sim.txt @@ -0,0 +1,64 @@ +x0 0x0 +x1 0x1 +x2 0x2 +x3 0x3 +x4 0x4 +x5 0x5 +x6 0x6 +x7 0x7 +x8 0x8 +x9 0x9 +x10 0xA +x11 0xB +x12 0xC +x13 0xD +x14 0xE +x15 0xF +x16 0x10 +x17 0x11 +x18 0x12 +x19 0x13 +x20 0x14 +x21 0x15 +x22 0x16 +x23 0x17 +x24 0x18 +x25 0x19 +x26 0x1A +x27 0x1B +x28 0x1C +x29 0x1D +x30 0x1E +x31 0x1F +x32 0x20 +x33 0x21 +x34 0x22 +x35 0x23 +x36 0x24 +x37 0x25 +x38 0x26 +x39 0x27 +x40 0x28 +x41 0x29 +x42 0x2A +x43 0x2B +x44 0x2C +x45 0x2D +x46 0x2E +x47 0x2F +x48 0x30 +x49 0x31 +x50 0x32 +x51 0x33 +x52 0x34 +x53 0x35 +x54 0x36 +x55 0x37 +x56 0x38 +x57 0x39 +x58 0x3A +x59 0x3B +x60 0x3C +x61 0x3D +x62 0x3E +x63 0x3F \ No newline at end of file diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index 04a3c19..b745640 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -24,8 +25,7 @@ typedef uint64_t SimValue; // Buffer size for reading from and writing to simulation data files. #define BUF_SIZE 200 -typedef std::unordered_map> SimVars; +typedef std::map> IOVars; typedef std::unordered_map> Inputs; @@ -38,14 +38,14 @@ class DFCXXSimulator { bool simulate(std::ifstream &in, std::ofstream &out); private: - uint64_t readInputData(std::ifstream &in, SimVars &inputMapping); - bool runSim(SimVars &input, SimVars &output, uint64_t count); - bool writeOutput(std::ofstream &out, SimVars &output, uint64_t count); + uint64_t readInputData(std::ifstream &in, IOVars &inputMapping); + bool runSim(IOVars &input, IOVars &output, uint64_t count); + bool writeOutput(std::ofstream &out, IOVars &output, uint64_t count); void processInput(RecordedValues &vals, Node &node, - SimVars &input, uint64_t ind); + IOVars &input, uint64_t ind); void processOutput(RecordedValues &vals, Node &node, - SimVars &output, uint64_t ind); + IOVars &output, uint64_t ind); void processConst(RecordedValues &vals, Node &node); void processMux(RecordedValues &vals, Node &node); template diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 93bc757..1f228d5 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -13,7 +13,7 @@ DFCXXSimulator::DFCXXSimulator(std::vector &nodes, uint64_t DFCXXSimulator::readInputData(std::ifstream &in, - SimVars &inputMapping) { + IOVars &inputMapping) { uint64_t ind = 0; std::string line; bool atLeastOne = false; @@ -38,13 +38,13 @@ uint64_t DFCXXSimulator::readInputData(std::ifstream &in, } void DFCXXSimulator::processInput(RecordedValues &vals, Node &node, - SimVars &input, uint64_t ind) { + IOVars &input, uint64_t ind) { auto name = std::string(DFVariable(node.var).getName()); vals[node] = input[name][ind]; } void DFCXXSimulator::processOutput(RecordedValues &vals, Node &node, - SimVars &output, uint64_t ind) { + IOVars &output, uint64_t ind) { auto name = std::string(DFVariable(node.var).getName()); // Take output's only connection and assign the existing source value. vals[node] = vals[inputs[node][0].source]; @@ -340,8 +340,8 @@ void DFCXXSimulator::processShiftRight(RecordedValues &vals, Node &node) { // No right bit shift for floats. } -bool DFCXXSimulator::runSim(SimVars &input, - SimVars &output, +bool DFCXXSimulator::runSim(IOVars &input, + IOVars &output, uint64_t count) { // Node->value mapping is initialized. This allows us // to rememeber the relevant value for the operand node. @@ -381,7 +381,7 @@ bool DFCXXSimulator::runSim(SimVars &input, } bool DFCXXSimulator::writeOutput(std::ofstream &out, - SimVars &output, + IOVars &output, uint64_t count) { auto outFunc = [&out, &output] (uint64_t iter) { for (auto &kv : output) { @@ -399,8 +399,8 @@ bool DFCXXSimulator::writeOutput(std::ofstream &out, bool DFCXXSimulator::simulate(std::ifstream &in, std::ofstream &out) { - SimVars input; - SimVars output; + IOVars input; + IOVars output; while (uint64_t count = readInputData(in, input)) { // If either the simulation itself or writing to output file // fails - return false. From ddac5f94ec84e216e148e053a3b9b9e3b3866409 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Tue, 20 Aug 2024 17:51:14 +0300 Subject: [PATCH 10/21] Simulation CLI fixes; subcommand sim now accepts only a single input data file instead of a vector. --- config.json | 3 +- examples/idct/idct.h | 3 -- src/main.cpp | 2 +- src/model/dfcxx/include/dfcxx/kernel.h | 2 +- src/model/dfcxx/lib/dfcxx/kernel.cpp | 14 +++-- src/options.h | 74 ++++---------------------- 6 files changed, 19 insertions(+), 79 deletions(-) diff --git a/config.json b/config.json index b8cb3fd..d22df37 100644 --- a/config.json +++ b/config.json @@ -9,6 +9,7 @@ "out_firrtl" : "" }, "sim": { - + "in" : "sim.txt", + "out" : "sim_out.txt" } } diff --git a/examples/idct/idct.h b/examples/idct/idct.h index e1ba5e1..3d48be3 100644 --- a/examples/idct/idct.h +++ b/examples/idct/idct.h @@ -29,9 +29,6 @@ class IDCT : public dfcxx::Kernel { DFVariable const8192 = constant.var(type, int64_t(8192)); DFVariable const4 = constant.var(type, int64_t(4)); - DFVariable constM256 = constant.var(type, int64_t(-256)); - DFVariable const255 = constant.var(type, int64_t(255)); - DFVariable W1 = constant.var(type, int64_t(2841)); DFVariable W2 = constant.var(type, int64_t(2676)); DFVariable W3 = constant.var(type, int64_t(2408)); diff --git a/src/main.cpp b/src/main.cpp index bdd36a8..87948dd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -53,7 +53,7 @@ int hlsMain(const HlsContext &context) { int simMain(const SimContext &context) { auto kernel = start(); - return !kernel->simulate(context.options.dataFiles(), + return !kernel->simulate(context.options.inFilePath, context.options.outFilePath); } diff --git a/src/model/dfcxx/include/dfcxx/kernel.h b/src/model/dfcxx/include/dfcxx/kernel.h index b5b4586..6acee51 100644 --- a/src/model/dfcxx/include/dfcxx/kernel.h +++ b/src/model/dfcxx/include/dfcxx/kernel.h @@ -68,7 +68,7 @@ class Kernel { const DFOutputPaths &outputPaths, const Scheduler &sched); - bool simulate(const std::vector &dataPaths, + bool simulate(const std::string &inDataPath, const std::string &outFilePath); }; diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index 93c0ec4..06a6cb9 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -82,20 +82,18 @@ bool Kernel::compile(const DFLatencyConfig &config, } -bool Kernel::simulate(const std::vector &dataPaths, +bool Kernel::simulate(const std::string &inDataPath, const std::string &outFilePath) { - bool result = true; std::vector sorted = topSort(graph.startNodes, graph.outputs, graph.nodes.size()); DFCXXSimulator sim(sorted, graph.inputs); - std::ofstream out(outFilePath, std::ios::out); - for (const std::string &path : dataPaths) { - std::ifstream input(path, std::ios::in); - sim.simulate(input, out); + std::ifstream input(inDataPath, std::ios::in); + if (!input || input.bad() || input.eof() || input.fail() || !input.is_open()) { + return false; } - - return result; + std::ofstream output(outFilePath, std::ios::out); + return sim.simulate(input, output); } } // namespace dfcxx diff --git a/src/options.h b/src/options.h index dea8fab..5a158eb 100644 --- a/src/options.h +++ b/src/options.h @@ -42,6 +42,7 @@ #define OUT_FIRRTL_JSON "out_firrtl" #define SIM_ID_JSON "sim" +#define SIM_IN_JSON "in" #define SIM_OUT_JSON "out" //===----------------------------------------------------------------------===// @@ -59,9 +60,8 @@ #define OUT_DFCIR_ARG CLI_ARG("out-dfcir") #define OUT_FIRRTL_ARG CLI_ARG("out-firrtl") -#define SIM_USAGE_FILES_ARG "files" +#define SIM_IN_ARG CLI_ARG("in") #define SIM_OUT_ARG CLI_ARG("out") -#define SIM_FILES_ARG CLI_ARG("files") //===----------------------------------------------------------------------===// @@ -273,81 +273,25 @@ struct HlsOptions final : public AppOptions { struct SimOptions final : public AppOptions { - // Custom usage description formatter (based on the default one). - // struct UsageFormatter: public CLI::Formatter { - // inline std::string make_usage(const CLI::App *app, - // std::string name) const override { - // std::stringstream out; - - // out << get_label("Usage") << ":" << (name.empty() ? "" : " ") << name; - - // std::vector groups = app->get_groups(); - - // // Print an Options badge if any options exist - // std::vector non_pos_options = - // app->get_options([](const CLI::Option *opt) { - // return opt->nonpositional(); - // }); - - // if(!non_pos_options.empty()) { - // out << " [" << get_label("OPTIONS") << "]"; - // } - // out << " " SIM_USAGE_FILES_ARG "..."; - - // // Positionals need to be listed here - // std::vector positionals = - // app->get_options([](const CLI::Option *opt) { - // return opt->get_positional(); - // }); - - // // Print out positionals if any are left - // if(!positionals.empty()) { - // // Convert to help names - // std::vector positional_names(positionals.size()); - // std::transform(positionals.begin(), - // positionals.end(), - // positional_names.begin(), - // [this](const CLI::Option *opt) { - // return make_option_usage(opt); - // }); - - // out << " " << CLI::detail::join(positional_names, " "); - // } - - // out << std::endl; - // return out.str(); - // } - // }; - SimOptions(AppOptions &parent): AppOptions(parent, SIM_CMD, "DFCxx simulation") { //options->formatter(std::make_shared()); // Named options. + options->add_option(SIM_IN_ARG, + inFilePath, + "Simulation input data path")->capture_default_str(); options->add_option(SIM_OUT_ARG, outFilePath, - "Simulation output path")->expected(1); - options->add_option(SIM_FILES_ARG, - files, - "Simulation output path"); - // For processing data files' paths. - // options->allow_extras(); - // auto *var = options; // Used for lambda variable passing. - // options->callback([&var]() { - // if (var->remaining_size() < 1) { - // throw CLI::ArgumentMismatch("input data files", -1, 0); - // } - // }); - } - - std::vector dataFiles() const { - return files; + "Simulation results output path")->capture_default_str(); } void fromJson(Json json) override { + get(json, SIM_IN_JSON, inFilePath); get(json, SIM_OUT_JSON, outFilePath); } + std::string inFilePath; std::string outFilePath; std::vector files; }; @@ -381,7 +325,7 @@ struct Options final : public AppOptions { void fromJson(Json json) override { hls.fromJson(json[HLS_ID_JSON]); - hls.fromJson(json[SIM_ID_JSON]); + sim.fromJson(json[SIM_ID_JSON]); } HlsOptions hls; From 38d04cfea9a22fda5b999c43ebd7029c882dcd5a Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Thu, 22 Aug 2024 05:28:12 +0300 Subject: [PATCH 11/21] [INCOMPLETE] DFCxx interfaces fixes. --- config.json | 5 +- src/main.cpp | 3 +- src/model/dfcxx/include/dfcxx/constant.h | 12 +- src/model/dfcxx/include/dfcxx/graph.h | 55 ---- src/model/dfcxx/include/dfcxx/io.h | 13 +- src/model/dfcxx/include/dfcxx/kernel.h | 17 +- src/model/dfcxx/include/dfcxx/kernmeta.h | 32 ++ src/model/dfcxx/include/dfcxx/kernstorage.h | 4 - src/model/dfcxx/include/dfcxx/offset.h | 11 +- .../include/dfcxx/typebuilders/builder.h | 4 +- src/model/dfcxx/include/dfcxx/types/fixed.h | 10 +- src/model/dfcxx/include/dfcxx/types/type.h | 14 +- .../dfcxx/include/dfcxx/varbuilders/builder.h | 24 +- src/model/dfcxx/include/dfcxx/vars/constant.h | 67 ++-- src/model/dfcxx/include/dfcxx/vars/scalar.h | 39 ++- src/model/dfcxx/include/dfcxx/vars/stream.h | 42 ++- src/model/dfcxx/include/dfcxx/vars/var.h | 79 +++-- src/model/dfcxx/includeDev/dfcxx/simulator.h | 8 +- src/model/dfcxx/lib/dfcxx/constant.cpp | 24 +- src/model/dfcxx/lib/dfcxx/graph.cpp | 27 -- src/model/dfcxx/lib/dfcxx/io.cpp | 42 ++- src/model/dfcxx/lib/dfcxx/kernel.cpp | 28 +- src/model/dfcxx/lib/dfcxx/kernstorage.cpp | 7 - src/model/dfcxx/lib/dfcxx/offset.cpp | 16 +- src/model/dfcxx/lib/dfcxx/simulator.cpp | 15 +- .../dfcxx/lib/dfcxx/typebuilders/builder.cpp | 20 +- src/model/dfcxx/lib/dfcxx/types/type.cpp | 6 +- .../dfcxx/lib/dfcxx/varbuilders/builder.cpp | 60 ++-- src/model/dfcxx/lib/dfcxx/vars/constant.cpp | 286 +++++++++--------- src/model/dfcxx/lib/dfcxx/vars/scalar.cpp | 258 ++++++++-------- src/model/dfcxx/lib/dfcxx/vars/stream.cpp | 258 ++++++++-------- src/model/dfcxx/lib/dfcxx/vars/var.cpp | 56 ++-- src/options.h | 11 +- 33 files changed, 716 insertions(+), 837 deletions(-) create mode 100644 src/model/dfcxx/include/dfcxx/kernmeta.h diff --git a/config.json b/config.json index d22df37..377b348 100644 --- a/config.json +++ b/config.json @@ -9,7 +9,8 @@ "out_firrtl" : "" }, "sim": { - "in" : "sim.txt", - "out" : "sim_out.txt" + "in" : "sim.txt", + "intermediate" : false, + "out" : "sim_out.txt" } } diff --git a/src/main.cpp b/src/main.cpp index 87948dd..86456b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,7 +54,8 @@ int hlsMain(const HlsContext &context) { int simMain(const SimContext &context) { auto kernel = start(); return !kernel->simulate(context.options.inFilePath, - context.options.outFilePath); + context.options.outFilePath, + context.options.intermediateResults); } int main(int argc, char **argv) { diff --git a/src/model/dfcxx/include/dfcxx/constant.h b/src/model/dfcxx/include/dfcxx/constant.h index e145e6b..4947f39 100644 --- a/src/model/dfcxx/include/dfcxx/constant.h +++ b/src/model/dfcxx/include/dfcxx/constant.h @@ -9,9 +9,7 @@ #ifndef DFCXX_CONSTANT_H #define DFCXX_CONSTANT_H -#include "dfcxx/graph.h" -#include "dfcxx/kernstorage.h" -#include "dfcxx/varbuilders/builder.h" +#include "dfcxx/kernmeta.h" namespace dfcxx { @@ -21,13 +19,9 @@ class Constant { friend Kernel; private: - Graph &graph; - GraphHelper helper; - VarBuilder &varBuilder; - KernStorage &storage; + KernMeta &meta; - Constant(Graph &graph, TypeBuilder &typeBuilder, - VarBuilder &varBuilder, KernStorage &storage); + Constant(KernMeta &meta); public: DFVariable var(const DFType &type, int64_t value); diff --git a/src/model/dfcxx/include/dfcxx/graph.h b/src/model/dfcxx/include/dfcxx/graph.h index 7bc2951..5d4e1ba 100644 --- a/src/model/dfcxx/include/dfcxx/graph.h +++ b/src/model/dfcxx/include/dfcxx/graph.h @@ -11,7 +11,6 @@ #include "dfcxx/channel.h" #include "dfcxx/node.h" -#include "dfcxx/typebuilders/builder.h" #include "dfcxx/vars/var.h" #include @@ -20,33 +19,7 @@ namespace dfcxx { -class GraphHelper; - -class Kernel; - -class IO; - -class Offset; - -class Constant; - -class Control; - -class DFCIRBuilder; - -class VarBuilder; - -class KernStorage; - class Graph { - friend GraphHelper; - friend Kernel; - friend IO; - friend Offset; - friend Constant; - friend Control; - friend DFCIRBuilder; - private: std::unordered_set nodes; std::unordered_set startNodes; @@ -69,34 +42,6 @@ class Graph { unsigned opInd, bool connect); }; -class GraphHelper { - friend IO; - friend Offset; - friend Constant; - friend Control; - -private: - Graph &graph; - - GraphHelper(Graph &graph, TypeBuilder &typeBuilder, - VarBuilder &varBuilder, KernStorage &storage); - -public: - TypeBuilder &typeBuilder; - VarBuilder &varBuilder; - KernStorage &storage; - - void addNode(DFVariableImpl *var, OpType type, NodeData data); - - void addNode(const DFVariable &var, OpType type, NodeData data); - - void addChannel(DFVariableImpl *source, DFVariableImpl *target, - unsigned opInd, bool connect); - - void addChannel(const DFVariable &source, const DFVariable &target, - unsigned opInd, bool connect); -}; - } // namespace dfcxx #endif // DFCXX_GRAPH_H diff --git a/src/model/dfcxx/include/dfcxx/io.h b/src/model/dfcxx/include/dfcxx/io.h index 24c5191..5ec0e66 100644 --- a/src/model/dfcxx/include/dfcxx/io.h +++ b/src/model/dfcxx/include/dfcxx/io.h @@ -9,10 +9,7 @@ #ifndef DFCXX_IO_H #define DFCXX_IO_H -#include "dfcxx/graph.h" -#include "dfcxx/kernstorage.h" -#include "dfcxx/typebuilders/builder.h" -#include "dfcxx/varbuilders/builder.h" +#include "dfcxx/kernmeta.h" namespace dfcxx { @@ -22,13 +19,9 @@ class IO { friend Kernel; private: - Graph &graph; - GraphHelper helper; - VarBuilder &varBuilder; - KernStorage &storage; + KernMeta &meta; - IO(Graph &graph, TypeBuilder &typeBuilder, - VarBuilder &builder, KernStorage &storage); + IO(KernMeta &meta); public: DFVariable input(const std::string &name, const DFType &type); diff --git a/src/model/dfcxx/include/dfcxx/kernel.h b/src/model/dfcxx/include/dfcxx/kernel.h index 6acee51..1921221 100644 --- a/src/model/dfcxx/include/dfcxx/kernel.h +++ b/src/model/dfcxx/include/dfcxx/kernel.h @@ -11,14 +11,11 @@ #include "dfcxx/constant.h" #include "dfcxx/control.h" -#include "dfcxx/graph.h" #include "dfcxx/io.h" -#include "dfcxx/kernstorage.h" +#include "dfcxx/kernmeta.h" #include "dfcxx/offset.h" -#include "dfcxx/typebuilders/builder.h" #include "dfcxx/typedefs.h" #include "dfcxx/types/types.h" -#include "dfcxx/varbuilders/builder.h" #include "dfcxx/vars/var.h" #include @@ -28,16 +25,9 @@ namespace dfcxx { -class DFCIRBuilder; - class Kernel { - friend DFCIRBuilder; - private: - KernStorage storage; - TypeBuilder typeBuilder; - VarBuilder varBuilder; - Graph graph; + KernMeta meta; protected: IO io; @@ -69,7 +59,8 @@ class Kernel { const Scheduler &sched); bool simulate(const std::string &inDataPath, - const std::string &outFilePath); + const std::string &outFilePath, + bool intermediateResults = false); }; diff --git a/src/model/dfcxx/include/dfcxx/kernmeta.h b/src/model/dfcxx/include/dfcxx/kernmeta.h new file mode 100644 index 0000000..42b65b8 --- /dev/null +++ b/src/model/dfcxx/include/dfcxx/kernmeta.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the Utopia HLS Project, under the Apache License v2.0 +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 ISP RAS (http://www.ispras.ru) +// +//===----------------------------------------------------------------------===// + +#ifndef DFCXX_KERNMETA_H +#define DFCXX_KERNMETA_H + +#include "dfcxx/graph.h" +#include "dfcxx/kernstorage.h" +#include "dfcxx/typebuilders/builder.h" +#include "dfcxx/varbuilders/builder.h" + +namespace dfcxx { + +struct KernelMeta { + Graph graph; + KernStorage storage; + TypeBuilder typeBuilder; + VarBuilder varBuilder; + + KernelMeta() = default; + KernelMeta(const KernelMeta &) = delete; + ~KernelMeta() = default; +}; + +} // namespace dfcxx + +#endif // DFCXX_KERNMETA_H diff --git a/src/model/dfcxx/include/dfcxx/kernstorage.h b/src/model/dfcxx/include/dfcxx/kernstorage.h index 444d820..3fc4331 100644 --- a/src/model/dfcxx/include/dfcxx/kernstorage.h +++ b/src/model/dfcxx/include/dfcxx/kernstorage.h @@ -24,12 +24,8 @@ class KernStorage { public: DFTypeImpl *addType(DFTypeImpl *type); - DFType addType(const DFType &type); - DFVariableImpl *addVariable(DFVariableImpl *var); - DFVariable addVariable(const DFVariable &var); - ~KernStorage(); }; diff --git a/src/model/dfcxx/include/dfcxx/offset.h b/src/model/dfcxx/include/dfcxx/offset.h index 216f5ce..aef3c68 100644 --- a/src/model/dfcxx/include/dfcxx/offset.h +++ b/src/model/dfcxx/include/dfcxx/offset.h @@ -9,9 +9,7 @@ #ifndef DFCXX_OFFSET_H #define DFCXX_OFFSET_H -#include "dfcxx/graph.h" -#include "dfcxx/kernstorage.h" -#include "dfcxx/varbuilders/builder.h" +#include "dfcxx/kernmeta.h" namespace dfcxx { @@ -21,12 +19,9 @@ class Offset { friend Kernel; private: - Graph &graph; - GraphHelper helper; - VarBuilder &varBuilder; - KernStorage &storage; + KernMeta &meta; - Offset(Graph &graph, TypeBuilder &typeBuilder, VarBuilder &builder, KernStorage &storage); + Offset(KernMeta &meta); public: DFVariable operator()(DFVariable &stream, int64_t offset); diff --git a/src/model/dfcxx/include/dfcxx/typebuilders/builder.h b/src/model/dfcxx/include/dfcxx/typebuilders/builder.h index 390fe6f..10dc22b 100644 --- a/src/model/dfcxx/include/dfcxx/typebuilders/builder.h +++ b/src/model/dfcxx/include/dfcxx/typebuilders/builder.h @@ -21,9 +21,7 @@ class TypeBuilder { DFTypeImpl *buildFloat(uint8_t expBits, uint8_t fracBits); - DFTypeImpl *buildShiftedType(DFTypeImpl &type, int8_t shift); - - DFType buildShiftedType(const DFType &type, int8_t shift); + DFTypeImpl *buildShiftedType(DFTypeImpl *type, int8_t shift); }; } // namespace dfcxx diff --git a/src/model/dfcxx/include/dfcxx/types/fixed.h b/src/model/dfcxx/include/dfcxx/types/fixed.h index 0616cc7..1d2cd40 100644 --- a/src/model/dfcxx/include/dfcxx/types/fixed.h +++ b/src/model/dfcxx/include/dfcxx/types/fixed.h @@ -13,16 +13,16 @@ namespace dfcxx { -enum SignMode { - UNSIGNED = 0, - SIGNED -}; - class TypeBuilder; class FixedType : DFTypeImpl { friend TypeBuilder; + enum SignMode { + UNSIGNED = 0, + SIGNED + }; + private: SignMode mode; uint8_t intBits; diff --git a/src/model/dfcxx/include/dfcxx/types/type.h b/src/model/dfcxx/include/dfcxx/types/type.h index 53b577e..027052c 100644 --- a/src/model/dfcxx/include/dfcxx/types/type.h +++ b/src/model/dfcxx/include/dfcxx/types/type.h @@ -13,17 +13,7 @@ namespace dfcxx { -class DFType; -class TypeBuilder; -class DFCIRTypeConverter; -class DFCIRBuilder; - class DFTypeImpl { - friend DFType; - friend TypeBuilder; - friend DFCIRTypeConverter; - friend DFCIRBuilder; - public: virtual ~DFTypeImpl() = default; @@ -44,10 +34,12 @@ class DFType { public: DFType(DFTypeImpl *impl); + + operator DFTypeImpl*(); DFType(const DFType &) = default; - DFTypeImpl *getImpl() const; + DFTypeImpl *getImpl(); uint16_t getTotalBits() const; diff --git a/src/model/dfcxx/include/dfcxx/varbuilders/builder.h b/src/model/dfcxx/include/dfcxx/varbuilders/builder.h index c26b7dd..032a68d 100644 --- a/src/model/dfcxx/include/dfcxx/varbuilders/builder.h +++ b/src/model/dfcxx/include/dfcxx/varbuilders/builder.h @@ -9,31 +9,23 @@ #ifndef DFCXX_VAR_BUILDER_H #define DFCXX_VAR_BUILDER_H +#include "dfcxx/kernmeta.h" #include "dfcxx/vars/vars.h" namespace dfcxx { class VarBuilder { public: - DFVariableImpl * buildStream(const std::string &name, IODirection direction, - GraphHelper &helper, DFTypeImpl &type); + DFVariableImpl *buildStream(const std::string &name, IODirection direction, + KernMeta &meta, DFTypeImpl &type); - DFVariableImpl * buildScalar(const std::string &name, IODirection direction, - GraphHelper &helper, DFTypeImpl &type); + DFVariableImpl *buildScalar(const std::string &name, IODirection direction, + KernMeta &meta, DFTypeImpl &type); - DFVariableImpl * buildConstant(GraphHelper &helper, DFTypeImpl &type, - ConstantTypeKind kind, ConstantValue value); + DFVariableImpl *buildConstant(KernMeta &meta, DFTypeImpl &type, + ConstantTypeKind kind, ConstantValue value); - DFVariable buildStream(const std::string &name, IODirection direction, - GraphHelper &helper, const DFType &type); - - DFVariable buildScalar(const std::string &name, IODirection direction, - GraphHelper &helper, const DFType &type); - - DFVariable buildConstant(GraphHelper &helper, const DFType &type, - ConstantTypeKind kind, ConstantValue value); - - DFVariable buildMuxCopy(const DFVariable &var, GraphHelper &helper); + DFVariableImpl *buildMuxCopy(DFVariableImpl *var, KernMeta &meta); }; } // namespace dfcxx diff --git a/src/model/dfcxx/include/dfcxx/vars/constant.h b/src/model/dfcxx/include/dfcxx/vars/constant.h index c2a1080..5487de6 100644 --- a/src/model/dfcxx/include/dfcxx/vars/constant.h +++ b/src/model/dfcxx/include/dfcxx/vars/constant.h @@ -13,31 +13,29 @@ namespace dfcxx { -enum ConstantTypeKind : uint8_t { - INT = 0, - UINT, - FLOAT -}; - -union ConstantValue { - int64_t int_; - uint64_t uint_; - double double_; -}; - class VarBuilder; -class DFCIRBuilder; class DFConstant : DFVariableImpl { friend VarBuilder; - friend DFCIRBuilder; + + enum ConstantTypeKind : uint8_t { + INT = 0, + UINT, + FLOAT + }; + + union ConstantValue { + int64_t int_; + uint64_t uint_; + double double_; + }; private: - DFTypeImpl &type; + DFTypeImpl *type; ConstantTypeKind kind; ConstantValue value; - DFConstant(GraphHelper &helper, DFTypeImpl &type, + DFConstant(KernMeta &meta, DFTypeImpl *type, ConstantTypeKind kind, ConstantValue value); public: @@ -49,42 +47,41 @@ class DFConstant : DFVariableImpl { double getDouble() const; -protected: - DFTypeImpl &getType() override; + DFTypeImpl *getType() override; - DFVariableImpl &operator+(DFVariableImpl &rhs) override; + DFVariableImpl *operator+(DFVariableImpl &rhs) override; - DFVariableImpl &operator-(DFVariableImpl &rhs) override; + DFVariableImpl *operator-(DFVariableImpl &rhs) override; - DFVariableImpl &operator*(DFVariableImpl &rhs) override; + DFVariableImpl *operator*(DFVariableImpl &rhs) override; - DFVariableImpl &operator/(DFVariableImpl &rhs) override; + DFVariableImpl *operator/(DFVariableImpl &rhs) override; - DFVariableImpl &operator&(DFVariableImpl &rhs) override; + DFVariableImpl *operator&(DFVariableImpl &rhs) override; - DFVariableImpl &operator|(DFVariableImpl &rhs) override; + DFVariableImpl *operator|(DFVariableImpl &rhs) override; - DFVariableImpl &operator^(DFVariableImpl &rhs) override; + DFVariableImpl *operator^(DFVariableImpl &rhs) override; - DFVariableImpl &operator!() override; + DFVariableImpl *operator!() override; - DFVariableImpl &operator-() override; + DFVariableImpl *operator-() override; - DFVariableImpl &operator<(DFVariableImpl &rhs) override; + DFVariableImpl *operator<(DFVariableImpl &rhs) override; - DFVariableImpl &operator<=(DFVariableImpl &rhs) override; + DFVariableImpl *operator<=(DFVariableImpl &rhs) override; - DFVariableImpl &operator>(DFVariableImpl &rhs) override; + DFVariableImpl *operator>(DFVariableImpl &rhs) override; - DFVariableImpl &operator>=(DFVariableImpl &rhs) override; + DFVariableImpl *operator>=(DFVariableImpl &rhs) override; - DFVariableImpl &operator==(DFVariableImpl &rhs) override; + DFVariableImpl *operator==(DFVariableImpl &rhs) override; - DFVariableImpl &operator!=(DFVariableImpl &rhs) override; + DFVariableImpl *operator!=(DFVariableImpl &rhs) override; - DFVariableImpl &operator<<(uint8_t bits) override; + DFVariableImpl *operator<<(uint8_t bits) override; - DFVariableImpl &operator>>(uint8_t bits) override; + DFVariableImpl *operator>>(uint8_t bits) override; ConstantTypeKind getKind() const; diff --git a/src/model/dfcxx/include/dfcxx/vars/scalar.h b/src/model/dfcxx/include/dfcxx/vars/scalar.h index 195b313..5e565f0 100644 --- a/src/model/dfcxx/include/dfcxx/vars/scalar.h +++ b/src/model/dfcxx/include/dfcxx/vars/scalar.h @@ -14,11 +14,9 @@ namespace dfcxx { class VarBuilder; -class DFCIRBuilder; class DFScalar : DFVariableImpl { friend VarBuilder; - friend DFCIRBuilder; private: DFTypeImpl &type; @@ -29,42 +27,41 @@ class DFScalar : DFVariableImpl { public: ~DFScalar() override = default; -protected: - DFTypeImpl &getType() override; + DFTypeImpl *getType() override; - DFVariableImpl &operator+(DFVariableImpl &rhs) override; + DFVariableImpl *operator+(DFVariableImpl &rhs) override; - DFVariableImpl &operator-(DFVariableImpl &rhs) override; + DFVariableImpl *operator-(DFVariableImpl &rhs) override; - DFVariableImpl &operator*(DFVariableImpl &rhs) override; + DFVariableImpl *operator*(DFVariableImpl &rhs) override; - DFVariableImpl &operator/(DFVariableImpl &rhs) override; + DFVariableImpl *operator/(DFVariableImpl &rhs) override; - DFVariableImpl &operator&(DFVariableImpl &rhs) override; + DFVariableImpl *operator&(DFVariableImpl &rhs) override; - DFVariableImpl &operator|(DFVariableImpl &rhs) override; + DFVariableImpl *operator|(DFVariableImpl &rhs) override; - DFVariableImpl &operator^(DFVariableImpl &rhs) override; + DFVariableImpl *operator^(DFVariableImpl &rhs) override; - DFVariableImpl &operator!() override; + DFVariableImpl *operator!() override; - DFVariableImpl &operator-() override; + DFVariableImpl *operator-() override; - DFVariableImpl &operator<(DFVariableImpl &rhs) override; + DFVariableImpl *operator<(DFVariableImpl &rhs) override; - DFVariableImpl &operator<=(DFVariableImpl &rhs) override; + DFVariableImpl *operator<=(DFVariableImpl &rhs) override; - DFVariableImpl &operator>(DFVariableImpl &rhs) override; + DFVariableImpl *operator>(DFVariableImpl &rhs) override; - DFVariableImpl &operator>=(DFVariableImpl &rhs) override; + DFVariableImpl *operator>=(DFVariableImpl &rhs) override; - DFVariableImpl &operator==(DFVariableImpl &rhs) override; + DFVariableImpl *operator==(DFVariableImpl &rhs) override; - DFVariableImpl &operator!=(DFVariableImpl &rhs) override; + DFVariableImpl *operator!=(DFVariableImpl &rhs) override; - DFVariableImpl &operator<<(uint8_t bits) override; + DFVariableImpl *operator<<(uint8_t bits) override; - DFVariableImpl &operator>>(uint8_t bits) override; + DFVariableImpl *operator>>(uint8_t bits) override; bool isScalar() const override; }; diff --git a/src/model/dfcxx/include/dfcxx/vars/stream.h b/src/model/dfcxx/include/dfcxx/vars/stream.h index 013b5e3..d6df9b3 100644 --- a/src/model/dfcxx/include/dfcxx/vars/stream.h +++ b/src/model/dfcxx/include/dfcxx/vars/stream.h @@ -14,58 +14,54 @@ namespace dfcxx { class VarBuilder; -class DFCIRBuilder; class DFStream : DFVariableImpl { friend VarBuilder; - friend DFCIRBuilder; private: DFTypeImpl &type; DFStream(const std::string &name, IODirection direction, - GraphHelper &helper, DFTypeImpl &type); + KernMeta &meta, DFTypeImpl *type); public: ~DFStream() override = default; -protected: + DFTypeImpl *getType() override; - DFTypeImpl &getType() override; + DFVariableImpl *operator+(DFVariableImpl &rhs) override; - DFVariableImpl &operator+(DFVariableImpl &rhs) override; + DFVariableImpl *operator-(DFVariableImpl &rhs) override; - DFVariableImpl &operator-(DFVariableImpl &rhs) override; + DFVariableImpl *operator*(DFVariableImpl &rhs) override; - DFVariableImpl &operator*(DFVariableImpl &rhs) override; + DFVariableImpl *operator/(DFVariableImpl &rhs) override; - DFVariableImpl &operator/(DFVariableImpl &rhs) override; + DFVariableImpl *operator&(DFVariableImpl &rhs) override; - DFVariableImpl &operator&(DFVariableImpl &rhs) override; + DFVariableImpl *operator|(DFVariableImpl &rhs) override; - DFVariableImpl &operator|(DFVariableImpl &rhs) override; + DFVariableImpl *operator^(DFVariableImpl &rhs) override; - DFVariableImpl &operator^(DFVariableImpl &rhs) override; + DFVariableImpl *operator!() override; - DFVariableImpl &operator!() override; + DFVariableImpl *operator-() override; - DFVariableImpl &operator-() override; + DFVariableImpl *operator<(DFVariableImpl &rhs) override; - DFVariableImpl &operator<(DFVariableImpl &rhs) override; + DFVariableImpl *operator<=(DFVariableImpl &rhs) override; - DFVariableImpl &operator<=(DFVariableImpl &rhs) override; + DFVariableImpl *operator>(DFVariableImpl &rhs) override; - DFVariableImpl &operator>(DFVariableImpl &rhs) override; + DFVariableImpl *operator>=(DFVariableImpl &rhs) override; - DFVariableImpl &operator>=(DFVariableImpl &rhs) override; + DFVariableImpl *operator==(DFVariableImpl &rhs) override; - DFVariableImpl &operator==(DFVariableImpl &rhs) override; + DFVariableImpl *operator!=(DFVariableImpl &rhs) override; - DFVariableImpl &operator!=(DFVariableImpl &rhs) override; + DFVariableImpl *operator<<(uint8_t bits) override; - DFVariableImpl &operator<<(uint8_t bits) override; - - DFVariableImpl &operator>>(uint8_t bits) override; + DFVariableImpl *operator>>(uint8_t bits) override; bool isStream() const override; }; diff --git a/src/model/dfcxx/include/dfcxx/vars/var.h b/src/model/dfcxx/include/dfcxx/vars/var.h index e67b1a1..caf3357 100644 --- a/src/model/dfcxx/include/dfcxx/vars/var.h +++ b/src/model/dfcxx/include/dfcxx/vars/var.h @@ -9,6 +9,7 @@ #ifndef DFCXX_VAR_H #define DFCXX_VAR_H +#include "dfcxx/kernmeta.h" #include "dfcxx/types/type.h" #include @@ -16,29 +17,23 @@ namespace dfcxx { -enum IODirection{ - NONE = 0, - INPUT, - OUTPUT -}; - -class GraphHelper; -class DFVariable; -class VarBuilder; -class DFCIRTypeConverter; -class DFCIRBuilder; - class DFVariableImpl { - friend DFVariable; - friend VarBuilder; - friend DFCIRTypeConverter; - friend DFCIRBuilder; -private: + enum IODirection{ + NONE = 0, + INPUT, + OUTPUT + }; + +protected: std::string name; IODirection direction; + KernMeta &meta; public: + DFVariableImpl(const std::string &name, IODirection direction, + KernMeta &meta); + virtual ~DFVariableImpl() = default; virtual bool isStream() const; @@ -47,53 +42,49 @@ class DFVariableImpl { virtual bool isConstant() const; -protected: - GraphHelper &helper; - - DFVariableImpl(const std::string &name, IODirection direction, - GraphHelper &helper); - std::string_view getName() const; IODirection getDirection() const; - virtual DFTypeImpl &getType() = 0; + const KernMeta &getMeta() const; - virtual DFVariableImpl &operator+(DFVariableImpl &rhs) = 0; + virtual DFTypeImpl *getType() = 0; - virtual DFVariableImpl &operator-(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator+(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator*(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator-(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator/(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator*(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator&(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator/(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator|(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator&(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator^(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator|(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator!() = 0; + virtual DFVariableImpl *operator^(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator-() = 0; + virtual DFVariableImpl *operator!() = 0; - virtual DFVariableImpl &operator<(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator-() = 0; - virtual DFVariableImpl &operator<=(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator<(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator>(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator<=(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator>=(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator>(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator==(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator>=(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator!=(DFVariableImpl &rhs) = 0; + virtual DFVariableImpl *operator==(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator<<(uint8_t bits) = 0; + virtual DFVariableImpl *operator!=(DFVariableImpl &rhs) = 0; - virtual DFVariableImpl &operator>>(uint8_t bits) = 0; + virtual DFVariableImpl *operator<<(uint8_t bits) = 0; - void connect(DFVariableImpl &connectee); + virtual DFVariableImpl *operator>>(uint8_t bits) = 0; + + void connect(DFVariableImpl *connectee); }; class DFVariable { @@ -103,6 +94,8 @@ class DFVariable { public: DFVariable(DFVariableImpl *impl); + operator DFVariableImpl*(); + DFVariable(const DFVariable &) = default; DFVariableImpl *getImpl() const; @@ -111,6 +104,8 @@ class DFVariable { IODirection getDirection() const; + const KernMeta &getMeta() const; + DFType getType() const; DFVariable operator+(const DFVariable &rhs); diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index b745640..d2ad680 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -34,13 +34,17 @@ typedef std::unordered_map RecordedValues; class DFCXXSimulator { public: DFCXXSimulator(std::vector &nodes, - Inputs &inputs); + Inputs &inputs, + bool intermediateResults); bool simulate(std::ifstream &in, std::ofstream &out); private: uint64_t readInputData(std::ifstream &in, IOVars &inputMapping); bool runSim(IOVars &input, IOVars &output, uint64_t count); bool writeOutput(std::ofstream &out, IOVars &output, uint64_t count); + + bool processOp(RecordedValues &vals, Node &node, + IOVars &input, uint64_t ind); void processInput(RecordedValues &vals, Node &node, IOVars &input, uint64_t ind); @@ -54,8 +58,10 @@ class DFCXXSimulator { void processUnaryOp(RecordedValues &vals, Node &node); void processShiftLeft(RecordedValues &vals, Node &node); void processShiftRight(RecordedValues &vals, Node &node); + std::vector &nodes; Inputs &inputs; + bool intermediateResults; }; } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/constant.cpp b/src/model/dfcxx/lib/dfcxx/constant.cpp index 93c3ff2..1a19cae 100644 --- a/src/model/dfcxx/lib/dfcxx/constant.cpp +++ b/src/model/dfcxx/lib/dfcxx/constant.cpp @@ -10,36 +10,32 @@ namespace dfcxx { -Constant::Constant(Graph &graph, TypeBuilder &typeBuilder, - VarBuilder &varBuilder, KernStorage &storage) : - graph(graph), - helper(graph, typeBuilder, varBuilder, storage), - varBuilder(varBuilder), storage(storage) {} +Constant::Constant(KernMeta &meta) : meta(meta) {} DFVariable Constant::var(const DFType &type, int64_t value) { - DFVariable var = varBuilder.buildConstant(helper, type, + auto *var = meta.varBuilder.buildConstant(meta, type, ConstantTypeKind::INT, ConstantValue{.int_ = value}); - storage.addVariable(var); - graph.addNode(var, OpType::CONST, NodeData{}); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::CONST, NodeData{}); return var; } DFVariable Constant::var(const DFType &type, uint64_t value) { - DFVariable var = varBuilder.buildConstant(helper, *(type.getImpl()), + auto *var = meta.varBuilder.buildConstant(helper, type, ConstantTypeKind::UINT, ConstantValue{.uint_ = value}); - storage.addVariable(var); - graph.addNode(var, OpType::CONST, NodeData{}); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::CONST, NodeData{}); return var; } DFVariable Constant::var(const DFType &type, double value) { - DFVariable var = varBuilder.buildConstant(helper, *(type.getImpl()), + auto *var = meta.varBuilder.buildConstant(helper, type, ConstantTypeKind::FLOAT, ConstantValue{.double_ = value}); - storage.addVariable(var); - graph.addNode(var, OpType::CONST, NodeData{}); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::CONST, NodeData{}); return var; } diff --git a/src/model/dfcxx/lib/dfcxx/graph.cpp b/src/model/dfcxx/lib/dfcxx/graph.cpp index 6e49791..5ae866d 100644 --- a/src/model/dfcxx/lib/dfcxx/graph.cpp +++ b/src/model/dfcxx/lib/dfcxx/graph.cpp @@ -46,31 +46,4 @@ void Graph::addChannel(const DFVariable &source, const DFVariable &target, addChannel(source.getImpl(), target.getImpl(), opInd, connect); } -GraphHelper::GraphHelper(Graph &graph, TypeBuilder &typeBuilder, - VarBuilder &varBuilder, - KernStorage &storage) : graph(graph), - typeBuilder(typeBuilder), - varBuilder(varBuilder), - storage(storage) {} - -void GraphHelper::addNode(DFVariableImpl *var, OpType type, NodeData data) { - graph.addNode(var, type, data); -} - -void GraphHelper::addNode(const DFVariable &var, OpType type, NodeData data) { - addNode(var.getImpl(), type, data); -} - -void GraphHelper::addChannel(DFVariableImpl *source, DFVariableImpl *target, - unsigned opInd, bool connect) { - graph.addChannel(source, target, opInd, connect); -} - -void GraphHelper::addChannel(const DFVariable &source, - const DFVariable &target, - unsigned opInd, - bool connect) { - graph.addChannel(source.getImpl(), target.getImpl(), opInd, connect); -} - } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/io.cpp b/src/model/dfcxx/lib/dfcxx/io.cpp index f9262c7..5281b3e 100644 --- a/src/model/dfcxx/lib/dfcxx/io.cpp +++ b/src/model/dfcxx/lib/dfcxx/io.cpp @@ -10,53 +10,47 @@ namespace dfcxx { -using IODirection = dfcxx::IODirection; +using IODirection = dfcxx::DFVariableImpl::IODirection; -IO::IO(Graph &graph, TypeBuilder &typeBuilder, VarBuilder &varBuilder, - KernStorage &storage) : graph(graph), helper(graph, - typeBuilder, - varBuilder, - storage), - varBuilder(varBuilder), - storage(storage) {} +IO::IO(KernMeta &meta) : meta(meta) {} DFVariable IO::input(const std::string &name, const DFType &type) { - DFVariable var = varBuilder.buildStream(name, + auto *var = meta.varBuilder.buildStream(name, IODirection::INPUT, - helper, + meta, type); - storage.addVariable(var); - graph.addNode(var, OpType::IN, NodeData{}); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::IN, NodeData{}); return var; } DFVariable IO::inputScalar(const std::string &name, const DFType &type) { - DFVariable var = varBuilder.buildScalar(name, + auto *var = meta.varBuilder.buildScalar(name, IODirection::INPUT, - helper, + meta, type); - storage.addVariable(var); - graph.addNode(var, OpType::IN, NodeData{}); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::IN, NodeData{}); return var; } DFVariable IO::output(const std::string &name, const DFType &type) { - DFVariable var = varBuilder.buildStream(name, + auto *var = meta.varBuilder.buildStream(name, IODirection::OUTPUT, - helper, + meta, type); - storage.addVariable(var); - graph.addNode(var, OpType::OUT, NodeData{}); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::OUT, NodeData{}); return var; } DFVariable IO::outputScalar(const std::string &name, const DFType &type) { - DFVariable var = varBuilder.buildScalar(name, + auto *var = meta.varBuilder.buildScalar(name, IODirection::OUTPUT, - helper, + meta, type); - storage.addVariable(var); - graph.addNode(var, OpType::OUT, NodeData{}); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::OUT, NodeData{}); return var; } diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index 06a6cb9..4d6b206 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -17,30 +17,27 @@ namespace dfcxx { -Kernel::Kernel() : storage(), typeBuilder(), varBuilder(), - graph(), io(graph, typeBuilder, varBuilder, storage), - offset(graph, typeBuilder, varBuilder, storage), - constant(graph, typeBuilder, varBuilder, storage), - control(graph, typeBuilder, varBuilder, storage) {} +Kernel::Kernel() : meta(), io(meta), offset(meta), + constant(meta), control(meta) {} DFType Kernel::dfUInt(uint8_t bits) { - DFTypeImpl *type = typeBuilder.buildFixed(SignMode::UNSIGNED, bits, 0); - return DFType(storage.addType(type)); + auto *type = meta.typeBuilder.buildFixed(SignMode::UNSIGNED, bits, 0); + return meta.storage.addType(type); } DFType Kernel::dfInt(uint8_t bits) { - DFTypeImpl *type = typeBuilder.buildFixed(SignMode::SIGNED, bits, 0); - return DFType(storage.addType(type)); + auto *type = meta.typeBuilder.buildFixed(SignMode::SIGNED, bits, 0); + return meta.storage.addType(type); } DFType Kernel::dfFloat(uint8_t expBits, uint8_t fracBits) { - DFTypeImpl *type = typeBuilder.buildFloat(expBits, fracBits); - return DFType(storage.addType(type)); + auto *type = meta.typeBuilder.buildFloat(expBits, fracBits); + return meta.storage.addType(type); } DFType Kernel::dfBool() { - DFTypeImpl *type = typeBuilder.buildBool(); - return DFType(storage.addType(type)); + auto *type = meta.typeBuilder.buildBool(); + return meta.storage.addType(type); } @@ -83,11 +80,12 @@ bool Kernel::compile(const DFLatencyConfig &config, bool Kernel::simulate(const std::string &inDataPath, - const std::string &outFilePath) { + const std::string &outFilePath, + bool intermediateResults) { std::vector sorted = topSort(graph.startNodes, graph.outputs, graph.nodes.size()); - DFCXXSimulator sim(sorted, graph.inputs); + DFCXXSimulator sim(sorted, graph.inputs, intermediateResults); std::ifstream input(inDataPath, std::ios::in); if (!input || input.bad() || input.eof() || input.fail() || !input.is_open()) { return false; diff --git a/src/model/dfcxx/lib/dfcxx/kernstorage.cpp b/src/model/dfcxx/lib/dfcxx/kernstorage.cpp index ab6f0c1..f94071b 100644 --- a/src/model/dfcxx/lib/dfcxx/kernstorage.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernstorage.cpp @@ -25,17 +25,10 @@ dfcxx::DFTypeImpl *KernStorage::addType(dfcxx::DFTypeImpl *type) { } } -DFType KernStorage::addType(const DFType &type) { - return DFType(addType(type.getImpl())); -} - DFVariableImpl *KernStorage::addVariable(DFVariableImpl *var) { return *(variables.insert(var).first); } -DFVariable KernStorage::addVariable(const DFVariable &var) { - return DFVariable(addVariable(var.getImpl())); -} KernStorage::~KernStorage() { for (DFTypeImpl *type: types) { diff --git a/src/model/dfcxx/lib/dfcxx/offset.cpp b/src/model/dfcxx/lib/dfcxx/offset.cpp index 130d60f..96a4b9b 100644 --- a/src/model/dfcxx/lib/dfcxx/offset.cpp +++ b/src/model/dfcxx/lib/dfcxx/offset.cpp @@ -11,19 +11,15 @@ namespace dfcxx { -Offset::Offset(Graph &graph, TypeBuilder &typeBuilder, VarBuilder &varBuilder, - KernStorage &storage) : graph(graph), helper(graph, typeBuilder, - varBuilder, storage), - varBuilder(varBuilder), - storage(storage) {} +Offset::Offset(KernMeta &meta) : meta(meta) {} DFVariable Offset::operator()(DFVariable &stream, int64_t offset) { if (!stream.isStream()) { throw std::exception(); } - DFVariable var = varBuilder.buildStream("", IODirection::NONE, - helper, stream.getType()); - storage.addVariable(var); - graph.addNode(var, OpType::OFFSET, NodeData{.offset = offset}); - graph.addChannel(stream, var, 0, false); + auto *var = meta.varBuilder.buildStream("", IODirection::NONE, + meta, stream.getType()); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::OFFSET, NodeData{.offset = offset}); + meta.graph.addChannel(stream, var, 0, false); return var; } diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 1f228d5..6fe8735 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -6,9 +6,10 @@ namespace dfcxx { -DFCXXSimulator::DFCXXSimulator(std::vector &nodes, - Inputs &inputs) : nodes(nodes), - inputs(inputs) {} +DFCXXSimulator::DFCXXSimulator(std::vector &nodes, Inputs &inputs, + bool intermediateResults) : + nodes(nodes), inputs(inputs), + intermediateResults(intermediateResults) {} @@ -340,6 +341,11 @@ void DFCXXSimulator::processShiftRight(RecordedValues &vals, Node &node) { // No right bit shift for floats. } +bool DFCXXSimulator::processOp(RecordedValues &vals, Node &node, + IOVars &input, uint64_t ind) { + if (intermediateResults) {} +} + bool DFCXXSimulator::runSim(IOVars &input, IOVars &output, uint64_t count) { @@ -350,6 +356,9 @@ bool DFCXXSimulator::runSim(IOVars &input, RecordedValues vals; for (uint64_t i = 0; i < count; ++i) { for (Node &node : nodes) { + if (!processOp(vals, node, i, input, output)) { + return false; + } switch (node.type) { case OFFSET: return false; // TODO: Add offset support in the future. diff --git a/src/model/dfcxx/lib/dfcxx/typebuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/typebuilders/builder.cpp index 8d1ce4d..644bc7b 100644 --- a/src/model/dfcxx/lib/dfcxx/typebuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/typebuilders/builder.cpp @@ -23,22 +23,18 @@ DFTypeImpl *TypeBuilder::buildFloat(uint8_t expBits, uint8_t fracBits) { return new FloatType(expBits, fracBits); } -DFTypeImpl *TypeBuilder::buildShiftedType(DFTypeImpl &type, int8_t shift) { - if (type.isFixed()) { - FixedType &casted = (FixedType &) (type); +DFTypeImpl *TypeBuilder::buildShiftedType(DFTypeImpl *type, int8_t shift) { + if (type->isFixed()) { + FixedType *casted = (FixedType *) (type); return buildFixed( - casted.getSign(), - uint8_t(int16_t(casted.getIntBits()) + shift), casted.getFracBits()); + casted->getSign(), + uint8_t(int16_t(casted->getIntBits()) + shift), casted->getFracBits()); } else { - FloatType &casted = (FloatType &) (type); + FloatType *casted = (FloatType *) (type); return buildFloat( - casted.getExpBits(), - uint8_t(uint16_t(casted.getFracBits()) + shift)); + casted->getExpBits(), + uint8_t(uint16_t(casted->getFracBits()) + shift)); } } -DFType TypeBuilder::buildShiftedType(const DFType &type, int8_t shift) { - return DFType(buildShiftedType(*(type.getImpl()), shift)); -} - } // namespace dfcxx \ No newline at end of file diff --git a/src/model/dfcxx/lib/dfcxx/types/type.cpp b/src/model/dfcxx/lib/dfcxx/types/type.cpp index 1d4b6e7..3925f27 100644 --- a/src/model/dfcxx/lib/dfcxx/types/type.cpp +++ b/src/model/dfcxx/lib/dfcxx/types/type.cpp @@ -24,7 +24,11 @@ bool DFTypeImpl::isFloat() const { DFType::DFType(DFTypeImpl *impl) : impl(impl) {} -DFTypeImpl *DFType::getImpl() const { +DFType::operator DFTypeImpl*() { + return impl; +} + +DFTypeImpl *DFType::getImpl() { return impl; } diff --git a/src/model/dfcxx/lib/dfcxx/varbuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/varbuilders/builder.cpp index d9f7719..7f396b9 100644 --- a/src/model/dfcxx/lib/dfcxx/varbuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/varbuilders/builder.cpp @@ -10,54 +10,38 @@ namespace dfcxx { -DFVariableImpl * -VarBuilder::buildStream(const std::string &name, IODirection direction, - GraphHelper &helper, DFTypeImpl &type) { - return new DFStream(name, direction, helper, type); +DFVariableImpl *VarBuilder::buildStream(const std::string &name, + IODirection direction, + KernMeta &meta, + DFTypeImpl *type) { + return new DFStream(name, direction, meta, type); } -DFVariableImpl * -VarBuilder::buildScalar(const std::string &name, IODirection direction, - GraphHelper &helper, DFTypeImpl &type) { +DFVariableImpl *VarBuilder::buildScalar(const std::string &name, + IODirection direction, + KernMeta &meta, + DFTypeImpl *type) { return new DFScalar(name, direction, helper, type); } -DFVariableImpl * -VarBuilder::buildConstant(GraphHelper &helper, DFTypeImpl &type, - ConstantTypeKind kind, ConstantValue value) { +DFVariableImpl *VarBuilder::buildConstant(KernMeta &meta, + DFTypeImpl *type, + ConstantTypeKind kind, + ConstantValue value) { return new DFConstant(helper, type, kind, value); } -DFVariable -VarBuilder::buildStream(const std::string &name, IODirection direction, - GraphHelper &helper, const DFType &type) { - return DFVariable(buildStream(name, direction, helper, *(type.getImpl()))); -} - -DFVariable -VarBuilder::buildScalar(const std::string &name, IODirection direction, - GraphHelper &helper, const DFType &type) { - return DFVariable(buildScalar(name, direction, helper, *(type.getImpl()))); -} - -DFVariable -VarBuilder::buildConstant(GraphHelper &helper, const DFType &type, - ConstantTypeKind kind, ConstantValue value) { - return DFVariable(buildConstant(helper, *(type.getImpl()), kind, value)); -} - -DFVariable -VarBuilder::buildMuxCopy(const DFVariable &var, GraphHelper &helper) { - if (var.isConstant()) { - return buildConstant(helper, var.getType(), - ((DFConstant *) (var.getImpl()))->getKind(), +DFVariableImpl *VarBuilder::buildMuxCopy(DFVariableImpl *var, KernMeta &meta) { + if (var->isConstant()) { + return buildConstant(meta, var->getType(), + ((DFConstant *) var)->getKind(), ConstantValue{}); - } else if (var.isScalar()) { - return buildScalar("", IODirection::NONE, helper, - var.getType()); + } else if (var->isScalar()) { + return buildScalar("", IODirection::NONE, meta, + var->getType()); } else /* if (var.isStream()) */ { - return buildStream("", IODirection::NONE, helper, - var.getType()); + return buildStream("", IODirection::NONE, meta, + var->getType()); } } diff --git a/src/model/dfcxx/lib/dfcxx/vars/constant.cpp b/src/model/dfcxx/lib/dfcxx/vars/constant.cpp index b3f4deb..c92bdbc 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/constant.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/constant.cpp @@ -14,16 +14,16 @@ namespace dfcxx { -DFConstant::DFConstant(GraphHelper &helper, dfcxx::DFTypeImpl &type, +DFConstant::DFConstant(KernMeta &meta, DFTypeImpl *type, ConstantTypeKind kind, ConstantValue value) : - DFVariableImpl("", IODirection::NONE, helper), - type(type), kind(kind), value(value) {} + DFVariableImpl("", IODirection::NONE, meta), + type(*type), kind(kind), value(value) {} -DFTypeImpl &DFConstant::getType() { - return type; +DFTypeImpl *DFConstant::getType() { + return &type; } -DFVariableImpl &DFConstant::operator+(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator+(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { ConstantValue val{}; @@ -39,18 +39,18 @@ DFVariableImpl &DFConstant::operator+(DFVariableImpl &rhs) { val.double_ = value.double_ + casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, type); + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::ADD, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::ADD, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator-(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator-(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { ConstantValue val{}; @@ -66,18 +66,18 @@ DFVariableImpl &DFConstant::operator-(DFVariableImpl &rhs) { val.double_ = value.double_ - casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, type); + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SUB, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SUB, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator*(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator*(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { ConstantValue val{}; @@ -93,18 +93,18 @@ DFVariableImpl &DFConstant::operator*(DFVariableImpl &rhs) { val.double_ = value.double_ * casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, type); + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::MUL, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::MUL, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator/(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator/(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { ConstantValue val{}; @@ -120,18 +120,18 @@ DFVariableImpl &DFConstant::operator/(DFVariableImpl &rhs) { val.double_ = value.double_ / casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, type); + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::DIV, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::DIV, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator&(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator&(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { ConstantValue val{}; @@ -148,18 +148,18 @@ DFVariableImpl &DFConstant::operator&(DFVariableImpl &rhs) { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, type); + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::AND, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::AND, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator|(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator|(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { ConstantValue val{}; @@ -176,18 +176,18 @@ DFVariableImpl &DFConstant::operator|(DFVariableImpl &rhs) { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, type); + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::OR, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::OR, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator^(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator^(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { ConstantValue val{}; @@ -204,18 +204,18 @@ DFVariableImpl &DFConstant::operator^(DFVariableImpl &rhs) { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, type); + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::XOR, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::XOR, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator!() { +DFVariableImpl *DFConstant::operator!() { DFVariableImpl *newVar; ConstantValue val{}; switch (kind) { @@ -230,14 +230,14 @@ DFVariableImpl &DFConstant::operator!() { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NOT, NodeData{}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NOT, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFConstant::operator-() { +DFVariableImpl *DFConstant::operator-() { DFVariableImpl *newVar; ConstantValue val{}; switch (kind) { @@ -251,16 +251,16 @@ DFVariableImpl &DFConstant::operator-() { val.double_ = -value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, type, kind, val); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NEG, NodeData{}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NEG, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFConstant::operator<(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator<(DFVariableImpl &rhs) { DFVariableImpl *newVar; - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { ConstantValue val{}; DFConstant &casted = (DFConstant &) (rhs); @@ -275,23 +275,23 @@ DFVariableImpl &DFConstant::operator<(DFVariableImpl &rhs) { val.uint_ = value.double_ < casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, + newVar = meta.varBuilder.buildConstant(meta, *newType, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, *newType); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::LESS, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::LESS, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator<=(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator<=(DFVariableImpl &rhs) { DFVariableImpl *newVar; - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { ConstantValue val{}; DFConstant &casted = (DFConstant &) (rhs); @@ -306,23 +306,23 @@ DFVariableImpl &DFConstant::operator<=(DFVariableImpl &rhs) { val.uint_ = value.double_ <= casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, + newVar = meta.varBuilder.buildConstant(meta, *newType, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, *newType); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::LESSEQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::LESSEQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator>(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator>(DFVariableImpl &rhs) { DFVariableImpl *newVar; - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { ConstantValue val{}; DFConstant &casted = (DFConstant &) (rhs); @@ -337,23 +337,23 @@ DFVariableImpl &DFConstant::operator>(DFVariableImpl &rhs) { val.uint_ = value.double_ > casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, + newVar = meta.varBuilder.buildConstant(meta, *newType, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, *newType); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::GREATER, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::GREATER, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator>=(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator>=(DFVariableImpl &rhs) { DFVariableImpl *newVar; - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { ConstantValue val{}; DFConstant &casted = (DFConstant &) (rhs); @@ -368,23 +368,23 @@ DFVariableImpl &DFConstant::operator>=(DFVariableImpl &rhs) { val.uint_ = value.double_ >= casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, + newVar = meta.varBuilder.buildConstant(meta, *newType, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, *newType); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::GREATEREQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::GREATEREQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator==(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator==(DFVariableImpl &rhs) { DFVariableImpl *newVar; - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { ConstantValue val{}; DFConstant &casted = (DFConstant &) (rhs); @@ -399,23 +399,23 @@ DFVariableImpl &DFConstant::operator==(DFVariableImpl &rhs) { val.uint_ = value.double_ == casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, + newVar = meta.varBuilder.buildConstant(meta, *newType, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, *newType); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::EQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::EQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator!=(DFVariableImpl &rhs) { +DFVariableImpl *DFConstant::operator!=(DFVariableImpl &rhs) { DFVariableImpl *newVar; - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { ConstantValue val{}; DFConstant &casted = (DFConstant &) (rhs); @@ -430,21 +430,21 @@ DFVariableImpl &DFConstant::operator!=(DFVariableImpl &rhs) { val.uint_ = value.double_ != casted.value.double_; break; } - newVar = helper.varBuilder.buildConstant(helper, + newVar = meta.varBuilder.buildConstant(meta, *newType, kind, val); } else { - newVar = helper.varBuilder.buildStream("", IODirection::NONE, helper, + newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, *newType); } - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NEQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NEQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFConstant::operator<<(uint8_t bits) { +DFVariableImpl *DFConstant::operator<<(uint8_t bits) { DFVariableImpl *newVar; ConstantValue val{}; switch (kind) { @@ -459,16 +459,16 @@ DFVariableImpl &DFConstant::operator<<(uint8_t bits) { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - DFTypeImpl *newType = helper.storage.addType( - helper.typeBuilder.buildShiftedType(type, bits)); - newVar = helper.varBuilder.buildConstant(helper, *newType, kind, val); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + DFTypeImpl *newType = meta.storage.addType( + meta.typeBuilder.buildShiftedType(type, bits)); + newVar = meta.varBuilder.buildConstant(meta, newType, kind, val); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFConstant::operator>>(uint8_t bits) { +DFVariableImpl *DFConstant::operator>>(uint8_t bits) { DFVariableImpl *newVar; ConstantValue val{}; switch (kind) { @@ -483,13 +483,13 @@ DFVariableImpl &DFConstant::operator>>(uint8_t bits) { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - DFTypeImpl *newType = helper.storage.addType( - helper.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); - newVar = helper.varBuilder.buildConstant(helper, *newType, kind, val); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + DFTypeImpl *newType = meta.storage.addType( + meta.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); + newVar = meta.varBuilder.buildConstant(meta, newType, kind, val); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } ConstantTypeKind DFConstant::getKind() const { diff --git a/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp b/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp index c2e47a7..e32992a 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp @@ -14,187 +14,187 @@ namespace dfcxx { DFScalar::DFScalar(const std::string &name, IODirection direction, - GraphHelper &helper, dfcxx::DFTypeImpl &type) : - DFVariableImpl(name, direction, helper), type(type) {} + KernMeta &meta, DFTypeImpl *type) : + DFVariableImpl(name, direction, meta), type(*type) {} -DFTypeImpl &DFScalar::getType() { - return type; +DFTypeImpl *DFScalar::getType() { + return &type; } -DFVariableImpl &DFScalar::operator+(DFVariableImpl &rhs) { +DFVariableImpl *DFScalar::operator+(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::ADD, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::ADD, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator-(DFVariableImpl &rhs) { +DFVariableImpl *DFScalar::operator-(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SUB, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SUB, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator*(DFVariableImpl &rhs) { +DFVariableImpl *DFScalar::operator*(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::MUL, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::MUL, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator/(DFVariableImpl &rhs) { +DFVariableImpl *DFScalar::operator/(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::DIV, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::DIV, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator&(DFVariableImpl &rhs) { +DFVariableImpl *DFScalar::operator&(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::AND, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::AND, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator|(DFVariableImpl &rhs) { +DFVariableImpl *DFScalar::operator|(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::OR, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::OR, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator^(DFVariableImpl &rhs) { +DFVariableImpl *DFScalar::operator^(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::XOR, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::XOR, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator!() { +DFVariableImpl *DFScalar::operator!() { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NOT, NodeData{}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NOT, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFScalar::operator-() { +DFVariableImpl *DFScalar::operator-() { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NEG, NodeData{}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NEG, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFScalar::operator<(DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFScalar::operator<(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::LESS, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::LESS, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator<=(DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFScalar::operator<=(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::LESSEQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::LESSEQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator>(DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFScalar::operator>(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::GREATER, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::GREATER, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator>=(DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFScalar::operator>=(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::GREATEREQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::GREATEREQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator==(DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFScalar::operator==(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::EQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::EQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator!=(DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFScalar::operator!=(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NEQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NEQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFScalar::operator<<(uint8_t bits) { - DFTypeImpl *newType = helper.storage.addType( - helper.typeBuilder.buildShiftedType(type, bits)); +DFVariableImpl *DFScalar::operator<<(uint8_t bits) { + DFTypeImpl *newType = meta.storage.addType( + meta.typeBuilder.buildShiftedType(type, bits)); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFScalar::operator>>(uint8_t bits) { - DFTypeImpl *newType = helper.storage.addType( - helper.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); +DFVariableImpl *DFScalar::operator>>(uint8_t bits) { + DFTypeImpl *newType = meta.storage.addType( + meta.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } bool DFScalar::isScalar() const { diff --git a/src/model/dfcxx/lib/dfcxx/vars/stream.cpp b/src/model/dfcxx/lib/dfcxx/vars/stream.cpp index 590a73e..24822c1 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/stream.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/stream.cpp @@ -14,187 +14,187 @@ namespace dfcxx { DFStream::DFStream(const std::string &name, IODirection direction, - GraphHelper &helper, dfcxx::DFTypeImpl &type) : - DFVariableImpl(name, direction, helper), type(type) {} + KernMeta &meta, DFTypeImpl *type) : + DFVariableImpl(name, direction, meta), type(*type) {} -DFTypeImpl &DFStream::getType() { - return type; +DFTypeImpl *DFStream::getType() { + return &type; } -DFVariableImpl &DFStream::operator+(dfcxx::DFVariableImpl &rhs) { +DFVariableImpl *DFStream::operator+(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::ADD, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::ADD, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator-(dfcxx::DFVariableImpl &rhs) { +DFVariableImpl *DFStream::operator-(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SUB, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SUB, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator*(dfcxx::DFVariableImpl &rhs) { +DFVariableImpl *DFStream::operator*(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::MUL, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::MUL, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator/(dfcxx::DFVariableImpl &rhs) { +DFVariableImpl *DFStream::operator/(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::DIV, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::DIV, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator&(dfcxx::DFVariableImpl &rhs) { +DFVariableImpl *DFStream::operator&(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::AND, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::AND, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator|(dfcxx::DFVariableImpl &rhs) { +DFVariableImpl *DFStream::operator|(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::OR, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::OR, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator^(dfcxx::DFVariableImpl &rhs) { +DFVariableImpl *DFStream::operator^(DFVariableImpl &rhs) { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::XOR, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::XOR, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator!() { +DFVariableImpl *DFStream::operator!() { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NOT, NodeData{}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NOT, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFStream::operator-() { +DFVariableImpl *DFStream::operator-() { DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, type); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NEG, NodeData{}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NEG, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFStream::operator<(dfcxx::DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFStream::operator<(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::LESS, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::LESS, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator<=(dfcxx::DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFStream::operator<=(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::LESSEQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::LESSEQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator>(dfcxx::DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFStream::operator>(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::GREATER, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::GREATER, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator>=(dfcxx::DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFStream::operator>=(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::GREATEREQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::GREATEREQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator==(dfcxx::DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFStream::operator==(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::EQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::EQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator!=(dfcxx::DFVariableImpl &rhs) { - DFTypeImpl *newType = helper.storage.addType(helper.typeBuilder.buildBool()); +DFVariableImpl *DFStream::operator!=(DFVariableImpl &rhs) { + DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::NEQ, NodeData{}); - helper.addChannel(this, newVar, 0, false); - helper.addChannel(&rhs, newVar, 1, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::NEQ, NodeData{}); + meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addChannel(&rhs, newVar, 1, false); + return newVar; } -DFVariableImpl &DFStream::operator<<(uint8_t bits) { - DFTypeImpl *newType = helper.storage.addType( - helper.typeBuilder.buildShiftedType(type, bits)); +DFVariableImpl *DFStream::operator<<(uint8_t bits) { + DFTypeImpl *newType = meta.storage.addType( + meta.typeBuilder.buildShiftedType(type, bits)); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } -DFVariableImpl &DFStream::operator>>(uint8_t bits) { - DFTypeImpl *newType = helper.storage.addType( - helper.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); +DFVariableImpl *DFStream::operator>>(uint8_t bits) { + DFTypeImpl *newType = meta.storage.addType( + meta.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); DFVariableImpl *newVar = - helper.varBuilder.buildStream("", IODirection::NONE, helper, *newType); - helper.storage.addVariable(newVar); - helper.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); - helper.addChannel(this, newVar, 0, false); - return *newVar; + meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); + meta.storage.addVariable(newVar); + meta.graph.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); + meta.graph.addChannel(this, newVar, 0, false); + return newVar; } bool DFStream::isStream() const { diff --git a/src/model/dfcxx/lib/dfcxx/vars/var.cpp b/src/model/dfcxx/lib/dfcxx/vars/var.cpp index 1fd5feb..71d8405 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/var.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/var.cpp @@ -14,9 +14,9 @@ namespace dfcxx { DFVariableImpl::DFVariableImpl(const std::string &name, IODirection direction, - GraphHelper &helper) : name(name), - direction(direction), - helper(helper) {} + KernMeta &meta) : name(name), + direction(direction), + meta(meta) {} std::string_view DFVariableImpl::getName() const { return name; @@ -38,12 +38,16 @@ bool DFVariableImpl::isConstant() const { return false; } -void DFVariableImpl::connect(dfcxx::DFVariableImpl &connectee) { - helper.addChannel(&connectee, this, 0, true); +void DFVariableImpl::connect(DFVariableImpl *connectee) { + meta.addChannel(connectee, this, 0, true); } DFVariable::DFVariable(DFVariableImpl *impl) : impl(impl) {} +DFVariable::operator DFVariableImpl*() { + return impl; +} + DFVariableImpl *DFVariable::getImpl() const { return impl; } @@ -56,76 +60,80 @@ IODirection DFVariable::getDirection() const { return impl->getDirection(); } +const KernMeta &DFVariable::getMeta() const { + return impl->getMeta(); +} + DFType DFVariable::getType() const { - return DFType(&(impl->getType())); + return DFType(impl->getType()); } DFVariable DFVariable::operator+(const DFVariable &rhs) { - return DFVariable(&(impl->operator+(*(rhs.impl)))); + return DFVariable(impl->operator+(*(rhs.impl))); } DFVariable DFVariable::operator-(const DFVariable &rhs) { - return DFVariable(&(impl->operator-(*(rhs.impl)))); + return DFVariable(impl->operator-(*(rhs.impl))); } DFVariable DFVariable::operator*(const DFVariable &rhs) { - return DFVariable(&(impl->operator*(*(rhs.impl)))); + return DFVariable(impl->operator*(*(rhs.impl))); } DFVariable DFVariable::operator/(const DFVariable &rhs) { - return DFVariable(&(impl->operator/(*(rhs.impl)))); + return DFVariable(impl->operator/(*(rhs.impl))); } DFVariable DFVariable::operator&(const DFVariable &rhs) { - return DFVariable(&(impl->operator&(*(rhs.impl)))); + return DFVariable(impl->operator&(*(rhs.impl))); } DFVariable DFVariable::operator|(const DFVariable &rhs) { - return DFVariable(&(impl->operator|(*(rhs.impl)))); + return DFVariable(impl->operator|(*(rhs.impl))); } DFVariable DFVariable::operator^(const DFVariable &rhs) { - return DFVariable(&(impl->operator^(*(rhs.impl)))); + return DFVariable(impl->operator^(*(rhs.impl))); } DFVariable DFVariable::operator!() { - return DFVariable(&(impl->operator!())); + return DFVariable(impl->operator!()); } DFVariable DFVariable::operator-() { - return DFVariable(&(impl->operator-())); + return DFVariable(impl->operator-()); } DFVariable DFVariable::operator<(const DFVariable &rhs) { - return DFVariable(&(impl->operator<(*(rhs.impl)))); + return DFVariable(impl->operator<(*(rhs.impl))); } DFVariable DFVariable::operator<=(const DFVariable &rhs) { - return DFVariable(&(impl->operator<=(*(rhs.impl)))); + return DFVariable(impl->operator<=(*(rhs.impl))); } DFVariable DFVariable::operator>(const DFVariable &rhs) { - return DFVariable(&(impl->operator>(*(rhs.impl)))); + return DFVariable(impl->operator>(*(rhs.impl))); } DFVariable DFVariable::operator>=(const DFVariable &rhs) { - return DFVariable(&(impl->operator>=(*(rhs.impl)))); + return DFVariable(impl->operator>=(*(rhs.impl))); } DFVariable DFVariable::operator==(const DFVariable &rhs) { - return DFVariable(&(impl->operator==(*(rhs.impl)))); + return DFVariable(impl->operator==(*(rhs.impl))); } DFVariable DFVariable::operator!=(const DFVariable &rhs) { - return DFVariable(&(impl->operator!=(*(rhs.impl)))); + return DFVariable(impl->operator!=(*(rhs.impl))); } DFVariable DFVariable::operator<<(uint8_t bits) { - return DFVariable(&(impl->operator<<(bits))); + return DFVariable(impl->operator<<(bits)); } DFVariable DFVariable::operator>>(uint8_t bits) { - return DFVariable(&(impl->operator>>(bits))); + return DFVariable(impl->operator>>(bits)); } bool DFVariable::isStream() const { @@ -141,7 +149,7 @@ bool DFVariable::isConstant() const { } void DFVariable::connect(const DFVariable &connectee) { - impl->connect(*(connectee.impl)); + impl->connect(connectee.impl); } DFVariable &DFVariable::operator=(const DFVariable &var) { diff --git a/src/options.h b/src/options.h index 5a158eb..d52556a 100644 --- a/src/options.h +++ b/src/options.h @@ -43,6 +43,7 @@ #define SIM_ID_JSON "sim" #define SIM_IN_JSON "in" +#define SIM_INTERMEDIATE_RESULTS_JSON "intermediate" #define SIM_OUT_JSON "out" //===----------------------------------------------------------------------===// @@ -61,6 +62,7 @@ #define OUT_FIRRTL_ARG CLI_ARG("out-firrtl") #define SIM_IN_ARG CLI_ARG("in") +#define SIM_INTERMEDIATE_RESULTS_FLAG CLI_FLAG("i") #define SIM_OUT_ARG CLI_ARG("out") //===----------------------------------------------------------------------===// @@ -281,17 +283,22 @@ struct SimOptions final : public AppOptions { options->add_option(SIM_IN_ARG, inFilePath, "Simulation input data path")->capture_default_str(); + schedGroup->add_flag(SIM_INTERMEDIATE_RESULTS_FLAG, + intermediateResults, + "Dump intermediate computations as well")->capture_default_str(); options->add_option(SIM_OUT_ARG, outFilePath, "Simulation results output path")->capture_default_str(); } void fromJson(Json json) override { - get(json, SIM_IN_JSON, inFilePath); - get(json, SIM_OUT_JSON, outFilePath); + get(json, SIM_IN_JSON, inFilePath); + get(json, SIM_INTERMEDIATE_RESULTS_JSON, intermediateResults); + get(json, SIM_OUT_JSON, outFilePath); } std::string inFilePath; + bool intermediateResults; std::string outFilePath; std::vector files; }; From bd65dbbeefccbe1ffbe872443eedcb87043b884e Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Thu, 22 Aug 2024 20:11:54 +0300 Subject: [PATCH 12/21] [COMPLETE] DFCxx interfaces fixes. --- config.json | 1 - src/main.cpp | 3 +- src/model/dfcxx/include/dfcxx/DFCXX.h | 6 +- src/model/dfcxx/include/dfcxx/control.h | 12 +- src/model/dfcxx/include/dfcxx/graph.h | 16 +- src/model/dfcxx/include/dfcxx/kernel.h | 7 +- src/model/dfcxx/include/dfcxx/kernmeta.h | 8 +- .../include/dfcxx/typebuilders/builder.h | 3 +- src/model/dfcxx/include/dfcxx/types/fixed.h | 1 + src/model/dfcxx/include/dfcxx/types/type.h | 2 +- .../dfcxx/include/dfcxx/varbuilders/builder.h | 20 ++- src/model/dfcxx/include/dfcxx/vars/constant.h | 18 ++- src/model/dfcxx/include/dfcxx/vars/scalar.h | 4 +- src/model/dfcxx/include/dfcxx/vars/stream.h | 2 + src/model/dfcxx/include/dfcxx/vars/var.h | 14 +- .../includeDev/dfcxx/IRbuilders/builder.h | 13 +- src/model/dfcxx/includeDev/dfcxx/simulator.h | 8 +- src/model/dfcxx/includeDev/dfcxx/utils.h | 5 +- .../dfcxx/lib/dfcxx/IRbuilders/builder.cpp | 60 ++++---- .../dfcxx/lib/dfcxx/IRbuilders/converter.cpp | 20 +-- src/model/dfcxx/lib/dfcxx/constant.cpp | 19 ++- src/model/dfcxx/lib/dfcxx/control.cpp | 17 +-- src/model/dfcxx/lib/dfcxx/graph.cpp | 38 +++-- src/model/dfcxx/lib/dfcxx/kernel.cpp | 20 ++- src/model/dfcxx/lib/dfcxx/offset.cpp | 3 +- src/model/dfcxx/lib/dfcxx/simulator.cpp | 137 ++++++++---------- .../dfcxx/lib/dfcxx/typebuilders/builder.cpp | 5 +- src/model/dfcxx/lib/dfcxx/types/fixed.cpp | 2 +- src/model/dfcxx/lib/dfcxx/types/type.cpp | 2 +- src/model/dfcxx/lib/dfcxx/utils.cpp | 14 +- .../dfcxx/lib/dfcxx/varbuilders/builder.cpp | 25 +--- src/model/dfcxx/lib/dfcxx/vars/constant.cpp | 122 +++++++++------- src/model/dfcxx/lib/dfcxx/vars/scalar.cpp | 12 +- src/model/dfcxx/lib/dfcxx/vars/stream.cpp | 12 +- src/model/dfcxx/lib/dfcxx/vars/var.cpp | 23 ++- src/options.h | 8 - 36 files changed, 344 insertions(+), 338 deletions(-) diff --git a/config.json b/config.json index 377b348..dd8208e 100644 --- a/config.json +++ b/config.json @@ -10,7 +10,6 @@ }, "sim": { "in" : "sim.txt", - "intermediate" : false, "out" : "sim_out.txt" } } diff --git a/src/main.cpp b/src/main.cpp index 86456b7..87948dd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,8 +54,7 @@ int hlsMain(const HlsContext &context) { int simMain(const SimContext &context) { auto kernel = start(); return !kernel->simulate(context.options.inFilePath, - context.options.outFilePath, - context.options.intermediateResults); + context.options.outFilePath); } int main(int argc, char **argv) { diff --git a/src/model/dfcxx/include/dfcxx/DFCXX.h b/src/model/dfcxx/include/dfcxx/DFCXX.h index 9e714bb..8b37b6c 100644 --- a/src/model/dfcxx/include/dfcxx/DFCXX.h +++ b/src/model/dfcxx/include/dfcxx/DFCXX.h @@ -9,7 +9,9 @@ #ifndef DFCXX_H #define DFCXX_H -#include "kernel.h" -#include "typedefs.h" +#include "dfcxx/kernel.h" +#include "dfcxx/typedefs.h" +#include "dfcxx/types/types.h" +#include "dfcxx/vars/vars.h" #endif // DFCXX_H diff --git a/src/model/dfcxx/include/dfcxx/control.h b/src/model/dfcxx/include/dfcxx/control.h index 97f938c..47cd240 100644 --- a/src/model/dfcxx/include/dfcxx/control.h +++ b/src/model/dfcxx/include/dfcxx/control.h @@ -9,9 +9,7 @@ #ifndef DFCXX_CONTROL_H #define DFCXX_CONTROL_H -#include "dfcxx/graph.h" -#include "dfcxx/kernstorage.h" -#include "dfcxx/varbuilders/builder.h" +#include "dfcxx/kernmeta.h" #include @@ -23,13 +21,9 @@ class Control { friend Kernel; private: - Graph &graph; - GraphHelper helper; - VarBuilder &varBuilder; - KernStorage &storage; + KernMeta &meta; - Control(Graph &graph, TypeBuilder &typeBuilder, - VarBuilder &varBuilder, KernStorage &storage); + Control(KernMeta &meta); public: DFVariable mux(DFVariable ctrl, std::initializer_list args); diff --git a/src/model/dfcxx/include/dfcxx/graph.h b/src/model/dfcxx/include/dfcxx/graph.h index 5d4e1ba..0aaa5fd 100644 --- a/src/model/dfcxx/include/dfcxx/graph.h +++ b/src/model/dfcxx/include/dfcxx/graph.h @@ -27,19 +27,23 @@ class Graph { std::unordered_map> outputs; std::unordered_map connections; - Graph() = default; +public: + const std::unordered_set& getNodes() const; + + const std::unordered_set& getStartNodes() const; + + const std::unordered_map> &getInputs() const; + + const std::unordered_map> &getOutputs() const; + + const std::unordered_map &getConnections() const; Node findNode(DFVariableImpl *var); void addNode(DFVariableImpl *var, OpType type, NodeData data); - void addNode(const DFVariable &var, OpType type, NodeData data); - void addChannel(DFVariableImpl *source, DFVariableImpl *target, unsigned opInd, bool connect); - - void addChannel(const DFVariable &source, const DFVariable &target, - unsigned opInd, bool connect); }; } // namespace dfcxx diff --git a/src/model/dfcxx/include/dfcxx/kernel.h b/src/model/dfcxx/include/dfcxx/kernel.h index 1921221..fd9e03f 100644 --- a/src/model/dfcxx/include/dfcxx/kernel.h +++ b/src/model/dfcxx/include/dfcxx/kernel.h @@ -15,7 +15,7 @@ #include "dfcxx/kernmeta.h" #include "dfcxx/offset.h" #include "dfcxx/typedefs.h" -#include "dfcxx/types/types.h" +#include "dfcxx/types/type.h" #include "dfcxx/vars/var.h" #include @@ -49,6 +49,8 @@ class Kernel { virtual ~Kernel() = default; virtual std::string_view getName() = 0; + + const Graph& getGraph() const; bool compile(const DFLatencyConfig &config, const std::vector &outputPaths, @@ -59,8 +61,7 @@ class Kernel { const Scheduler &sched); bool simulate(const std::string &inDataPath, - const std::string &outFilePath, - bool intermediateResults = false); + const std::string &outFilePath); }; diff --git a/src/model/dfcxx/include/dfcxx/kernmeta.h b/src/model/dfcxx/include/dfcxx/kernmeta.h index 42b65b8..a1d3715 100644 --- a/src/model/dfcxx/include/dfcxx/kernmeta.h +++ b/src/model/dfcxx/include/dfcxx/kernmeta.h @@ -16,15 +16,15 @@ namespace dfcxx { -struct KernelMeta { +struct KernMeta { Graph graph; KernStorage storage; TypeBuilder typeBuilder; VarBuilder varBuilder; - KernelMeta() = default; - KernelMeta(const KernelMeta &) = delete; - ~KernelMeta() = default; + KernMeta() = default; + KernMeta(const KernMeta &) = delete; + ~KernMeta() = default; }; } // namespace dfcxx diff --git a/src/model/dfcxx/include/dfcxx/typebuilders/builder.h b/src/model/dfcxx/include/dfcxx/typebuilders/builder.h index 10dc22b..bf8bab7 100644 --- a/src/model/dfcxx/include/dfcxx/typebuilders/builder.h +++ b/src/model/dfcxx/include/dfcxx/typebuilders/builder.h @@ -15,7 +15,8 @@ namespace dfcxx { class TypeBuilder { public: - DFTypeImpl *buildFixed(SignMode mode, uint8_t intBits, uint8_t fracBits); + DFTypeImpl *buildFixed(FixedType::SignMode mode, uint8_t intBits, + uint8_t fracBits); DFTypeImpl *buildBool(); diff --git a/src/model/dfcxx/include/dfcxx/types/fixed.h b/src/model/dfcxx/include/dfcxx/types/fixed.h index 1d2cd40..3572399 100644 --- a/src/model/dfcxx/include/dfcxx/types/fixed.h +++ b/src/model/dfcxx/include/dfcxx/types/fixed.h @@ -18,6 +18,7 @@ class TypeBuilder; class FixedType : DFTypeImpl { friend TypeBuilder; +public: enum SignMode { UNSIGNED = 0, SIGNED diff --git a/src/model/dfcxx/include/dfcxx/types/type.h b/src/model/dfcxx/include/dfcxx/types/type.h index 027052c..1cfbbd8 100644 --- a/src/model/dfcxx/include/dfcxx/types/type.h +++ b/src/model/dfcxx/include/dfcxx/types/type.h @@ -35,7 +35,7 @@ class DFType { public: DFType(DFTypeImpl *impl); - operator DFTypeImpl*(); + operator DFTypeImpl*() const; DFType(const DFType &) = default; diff --git a/src/model/dfcxx/include/dfcxx/varbuilders/builder.h b/src/model/dfcxx/include/dfcxx/varbuilders/builder.h index 032a68d..db3e0b8 100644 --- a/src/model/dfcxx/include/dfcxx/varbuilders/builder.h +++ b/src/model/dfcxx/include/dfcxx/varbuilders/builder.h @@ -9,23 +9,27 @@ #ifndef DFCXX_VAR_BUILDER_H #define DFCXX_VAR_BUILDER_H -#include "dfcxx/kernmeta.h" #include "dfcxx/vars/vars.h" namespace dfcxx { +struct KernMeta; // Forward declaration to omit circicular dependency. + class VarBuilder { public: - DFVariableImpl *buildStream(const std::string &name, IODirection direction, - KernMeta &meta, DFTypeImpl &type); + DFVariableImpl *buildStream(const std::string &name, + DFVariableImpl::IODirection direction, + KernMeta &meta, DFTypeImpl *type); - DFVariableImpl *buildScalar(const std::string &name, IODirection direction, - KernMeta &meta, DFTypeImpl &type); + DFVariableImpl *buildScalar(const std::string &name, + DFVariableImpl::IODirection direction, + KernMeta &meta, DFTypeImpl *type); - DFVariableImpl *buildConstant(KernMeta &meta, DFTypeImpl &type, - ConstantTypeKind kind, ConstantValue value); + DFVariableImpl *buildConstant(KernMeta &meta, + DFTypeImpl *type, + DFConstant::Value value); - DFVariableImpl *buildMuxCopy(DFVariableImpl *var, KernMeta &meta); + DFVariableImpl *buildClone(DFVariableImpl *var); }; } // namespace dfcxx diff --git a/src/model/dfcxx/include/dfcxx/vars/constant.h b/src/model/dfcxx/include/dfcxx/vars/constant.h index 5487de6..9fce62e 100644 --- a/src/model/dfcxx/include/dfcxx/vars/constant.h +++ b/src/model/dfcxx/include/dfcxx/vars/constant.h @@ -18,25 +18,27 @@ class VarBuilder; class DFConstant : DFVariableImpl { friend VarBuilder; - enum ConstantTypeKind : uint8_t { +public: + enum TypeKind : uint8_t { INT = 0, UINT, FLOAT }; - union ConstantValue { + union Value { int64_t int_; uint64_t uint_; double double_; }; private: - DFTypeImpl *type; - ConstantTypeKind kind; - ConstantValue value; + DFTypeImpl &type; + TypeKind kind; + Value value; + + DFConstant(KernMeta &meta, DFTypeImpl *type, Value value); - DFConstant(KernMeta &meta, DFTypeImpl *type, - ConstantTypeKind kind, ConstantValue value); + DFVariableImpl *clone() const override; public: ~DFConstant() override = default; @@ -83,7 +85,7 @@ class DFConstant : DFVariableImpl { DFVariableImpl *operator>>(uint8_t bits) override; - ConstantTypeKind getKind() const; + TypeKind getKind() const; bool isConstant() const override; }; diff --git a/src/model/dfcxx/include/dfcxx/vars/scalar.h b/src/model/dfcxx/include/dfcxx/vars/scalar.h index 5e565f0..7ea6e16 100644 --- a/src/model/dfcxx/include/dfcxx/vars/scalar.h +++ b/src/model/dfcxx/include/dfcxx/vars/scalar.h @@ -22,7 +22,9 @@ class DFScalar : DFVariableImpl { DFTypeImpl &type; DFScalar(const std::string &name, IODirection direction, - GraphHelper &helper, DFTypeImpl &type); + KernMeta &meta, DFTypeImpl *type); + + DFVariableImpl *clone() const override; public: ~DFScalar() override = default; diff --git a/src/model/dfcxx/include/dfcxx/vars/stream.h b/src/model/dfcxx/include/dfcxx/vars/stream.h index d6df9b3..5ace679 100644 --- a/src/model/dfcxx/include/dfcxx/vars/stream.h +++ b/src/model/dfcxx/include/dfcxx/vars/stream.h @@ -24,6 +24,8 @@ class DFStream : DFVariableImpl { DFStream(const std::string &name, IODirection direction, KernMeta &meta, DFTypeImpl *type); + DFVariableImpl *clone() const override; + public: ~DFStream() override = default; diff --git a/src/model/dfcxx/include/dfcxx/vars/var.h b/src/model/dfcxx/include/dfcxx/vars/var.h index caf3357..da1d246 100644 --- a/src/model/dfcxx/include/dfcxx/vars/var.h +++ b/src/model/dfcxx/include/dfcxx/vars/var.h @@ -9,16 +9,20 @@ #ifndef DFCXX_VAR_H #define DFCXX_VAR_H -#include "dfcxx/kernmeta.h" -#include "dfcxx/types/type.h" +#include "dfcxx/types/types.h" #include #include namespace dfcxx { +class VarBuilder; +struct KernMeta; // Forward declaration to omit circicular dependency. + class DFVariableImpl { + friend VarBuilder; +public: enum IODirection{ NONE = 0, INPUT, @@ -30,6 +34,8 @@ class DFVariableImpl { IODirection direction; KernMeta &meta; + virtual DFVariableImpl *clone() const = 0; + public: DFVariableImpl(const std::string &name, IODirection direction, KernMeta &meta); @@ -94,7 +100,7 @@ class DFVariable { public: DFVariable(DFVariableImpl *impl); - operator DFVariableImpl*(); + operator DFVariableImpl*() const; DFVariable(const DFVariable &) = default; @@ -102,7 +108,7 @@ class DFVariable { std::string_view getName() const; - IODirection getDirection() const; + DFVariableImpl::IODirection getDirection() const; const KernMeta &getMeta() const; diff --git a/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h b/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h index c6e2b02..f449206 100644 --- a/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h +++ b/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h @@ -22,20 +22,17 @@ namespace dfcxx { class DFCIRBuilder { private: mlir::MLIRContext ctx; - mlir::OpBuilder builder; - std::unordered_map map; mlir::OwningOpRef module; DFCIRTypeConverter conv; - std::unordered_map> muxMap; + //std::unordered_map> muxMap; - void buildKernelBody(Graph *graph, mlir::OpBuilder &builder); + void translate(Node node, const Graph &graph, mlir::OpBuilder &builder, + std::unordered_map &map); + + void buildKernelBody(const Graph &graph, mlir::OpBuilder &builder); mlir::dfcir::KernelOp buildKernel(Kernel *kern, mlir::OpBuilder &builder); - mlir::ModuleOp buildModule(Kernel *kern, mlir::OpBuilder &builder); - - void translate(Node node, Graph *graph, mlir::OpBuilder &builder); - public: DFCIRBuilder(); diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index d2ad680..a9cdee0 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -34,17 +34,13 @@ typedef std::unordered_map RecordedValues; class DFCXXSimulator { public: DFCXXSimulator(std::vector &nodes, - Inputs &inputs, - bool intermediateResults); + const Inputs &inputs); bool simulate(std::ifstream &in, std::ofstream &out); private: uint64_t readInputData(std::ifstream &in, IOVars &inputMapping); bool runSim(IOVars &input, IOVars &output, uint64_t count); bool writeOutput(std::ofstream &out, IOVars &output, uint64_t count); - - bool processOp(RecordedValues &vals, Node &node, - IOVars &input, uint64_t ind); void processInput(RecordedValues &vals, Node &node, IOVars &input, uint64_t ind); @@ -60,7 +56,7 @@ class DFCXXSimulator { void processShiftRight(RecordedValues &vals, Node &node); std::vector &nodes; - Inputs &inputs; + const Inputs &inputs; bool intermediateResults; }; diff --git a/src/model/dfcxx/includeDev/dfcxx/utils.h b/src/model/dfcxx/includeDev/dfcxx/utils.h index b136b26..7b00a2d 100644 --- a/src/model/dfcxx/includeDev/dfcxx/utils.h +++ b/src/model/dfcxx/includeDev/dfcxx/utils.h @@ -18,10 +18,7 @@ namespace dfcxx { -std::vector topSort(std::unordered_set startNodes, - std::unordered_map> outs, - size_t nodesCount); +std::vector topSort(const Graph &graph); } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp index 8302d73..1f35c79 100644 --- a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp @@ -13,55 +13,46 @@ namespace dfcxx { -DFCIRBuilder::DFCIRBuilder() : ctx(), builder(&ctx), conv(&ctx) { - // We are allowed to initialize 'builder'-field before loading - // dialects as OpBuilder only stores the pointer to MLIRContext - // and doesn't check any of its state. +DFCIRBuilder::DFCIRBuilder() : ctx(), conv(&ctx) { ctx.getOrLoadDialect(); } -void DFCIRBuilder::buildKernelBody(Graph *graph, mlir::OpBuilder &builder) { - std::vector sorted = topSort(graph->startNodes, - graph->outputs, - graph->nodes.size()); +void DFCIRBuilder::buildKernelBody(const Graph &graph, mlir::OpBuilder &builder) { + std::vector sorted = topSort(graph); + std::unordered_map map; for (Node node : sorted) { - translate(node, graph, builder); + translate(node, graph, builder, map); } } -mlir::dfcir::KernelOp -DFCIRBuilder::buildKernel(dfcxx::Kernel *kern, mlir::OpBuilder &builder) { +mlir::dfcir::KernelOp DFCIRBuilder::buildKernel(Kernel *kern, + mlir::OpBuilder &builder) { auto kernel = builder.create(builder.getUnknownLoc(), kern->getName()); builder.setInsertionPointToStart(&kernel.getBody().emplaceBlock()); - buildKernelBody(&kern->graph, builder); + buildKernelBody(kern->getGraph(), builder); return kernel; } -mlir::ModuleOp -DFCIRBuilder::buildModule(dfcxx::Kernel *kern, mlir::OpBuilder &builder) { - auto module = builder.create(builder.getUnknownLoc()); - builder.setInsertionPointToStart(module.getBody()); - buildKernel(kern, builder); - return module; -} - -mlir::ModuleOp DFCIRBuilder::buildModule(dfcxx::Kernel *kern) { +mlir::ModuleOp DFCIRBuilder::buildModule(Kernel *kern) { assert(ctx.getLoadedDialect() != nullptr); mlir::OpBuilder builder(&ctx); - module = buildModule(kern, builder); + module = builder.create(builder.getUnknownLoc()); + builder.setInsertionPointToStart(module->getBody()); + buildKernel(kern, builder); return module.get(); } -void DFCIRBuilder::translate(dfcxx::Node node, dfcxx::Graph *graph, - mlir::OpBuilder &builder) { +void DFCIRBuilder::translate(Node node, const Graph &graph, + mlir::OpBuilder &builder, + std::unordered_map &map) { auto loc = builder.getUnknownLoc(); - - const auto &ins = graph->inputs[node]; + + const auto &ins = graph.getInputs().at(node); auto nameAttr = mlir::StringAttr::get(&ctx, node.var->getName()); @@ -108,21 +99,21 @@ void DFCIRBuilder::translate(dfcxx::Node node, dfcxx::Graph *graph, auto constant = (DFConstant *) (node.var); int64_t val; mlir::IntegerType attrType; - unsigned width = constant->getType().getTotalBits(); + unsigned width = constant->getType()->getTotalBits(); switch (constant->getKind()) { - case INT: + case DFConstant::TypeKind::INT: val = constant->getInt(); attrType = mlir::IntegerType::get(builder.getContext(), width, mlir::IntegerType::Signed); break; - case UINT: { + case DFConstant::TypeKind::UINT: { auto tmpU = constant->getUInt(); memcpy(&val, &tmpU, sizeof(val)); attrType = mlir::IntegerType::get(builder.getContext(), width, mlir::IntegerType::Unsigned); break; } - case FLOAT: { + case DFConstant::TypeKind::FLOAT: { auto tmpD = constant->getDouble(); memcpy(&val, &tmpD, sizeof(val)); attrType = mlir::IntegerType::get(builder.getContext(), width, @@ -148,9 +139,9 @@ void DFCIRBuilder::translate(dfcxx::Node node, dfcxx::Graph *graph, mux.push_back(map[ins[ind].source]); } } - muxMap[node] = mux; + auto newOp = builder.create(loc, conv[node.var], - map[ctrl], muxMap[node]); + map[ctrl], mux); map[node] = newOp.getRes(); break; } @@ -300,8 +291,9 @@ void DFCIRBuilder::translate(dfcxx::Node node, dfcxx::Graph *graph, break; } } - if (graph->connections.find(node) != graph->connections.end()) { - auto conSrc = graph->connections.at(node).source; + auto &connections = graph.getConnections(); + if (connections.find(node) != connections.end()) { + auto conSrc = connections.at(node).source; builder.create(loc, map[node], map[conSrc]); } } diff --git a/src/model/dfcxx/lib/dfcxx/IRbuilders/converter.cpp b/src/model/dfcxx/lib/dfcxx/IRbuilders/converter.cpp index d78f3e7..75c6bbf 100644 --- a/src/model/dfcxx/lib/dfcxx/IRbuilders/converter.cpp +++ b/src/model/dfcxx/lib/dfcxx/IRbuilders/converter.cpp @@ -13,18 +13,18 @@ namespace dfcxx { DFCIRTypeConverter::DFCIRTypeConverter(mlir::MLIRContext *ctx) : ctx(ctx) {} mlir::Type DFCIRTypeConverter::operator[](dfcxx::DFVariableImpl *var) { - const DFTypeImpl &type = var->getType(); + auto *type = var->getType(); mlir::Type newInnerType; - if (type.isFixed()) { - const FixedType &casted = (const FixedType &) (type); - newInnerType = mlir::dfcir::DFCIRFixedType::get(ctx, casted.isSigned(), - casted.getIntBits(), - casted.getFracBits()); - } else if (type.isFloat()) { - const FloatType &casted = (const FloatType &) (type); - newInnerType = mlir::dfcir::DFCIRFloatType::get(ctx, casted.getExpBits(), - casted.getFracBits()); + if (type->isFixed()) { + auto *casted = (FixedType *) (type); + newInnerType = mlir::dfcir::DFCIRFixedType::get(ctx, casted->isSigned(), + casted->getIntBits(), + casted->getFracBits()); + } else if (type->isFloat()) { + auto *casted = (FloatType *) (type); + newInnerType = mlir::dfcir::DFCIRFloatType::get(ctx, casted->getExpBits(), + casted->getFracBits()); } else { return nullptr; } diff --git a/src/model/dfcxx/lib/dfcxx/constant.cpp b/src/model/dfcxx/lib/dfcxx/constant.cpp index 1a19cae..0d57d2a 100644 --- a/src/model/dfcxx/lib/dfcxx/constant.cpp +++ b/src/model/dfcxx/lib/dfcxx/constant.cpp @@ -14,26 +14,29 @@ Constant::Constant(KernMeta &meta) : meta(meta) {} DFVariable Constant::var(const DFType &type, int64_t value) { auto *var = meta.varBuilder.buildConstant(meta, type, - ConstantTypeKind::INT, - ConstantValue{.int_ = value}); + DFConstant::Value{ + .int_ = value + }); meta.storage.addVariable(var); meta.graph.addNode(var, OpType::CONST, NodeData{}); return var; } DFVariable Constant::var(const DFType &type, uint64_t value) { - auto *var = meta.varBuilder.buildConstant(helper, type, - ConstantTypeKind::UINT, - ConstantValue{.uint_ = value}); + auto *var = meta.varBuilder.buildConstant(meta, type, + DFConstant::Value{ + .uint_ = value + }); meta.storage.addVariable(var); meta.graph.addNode(var, OpType::CONST, NodeData{}); return var; } DFVariable Constant::var(const DFType &type, double value) { - auto *var = meta.varBuilder.buildConstant(helper, type, - ConstantTypeKind::FLOAT, - ConstantValue{.double_ = value}); + auto *var = meta.varBuilder.buildConstant(meta, type, + DFConstant::Value{ + .double_ = value + }); meta.storage.addVariable(var); meta.graph.addNode(var, OpType::CONST, NodeData{}); return var; diff --git a/src/model/dfcxx/lib/dfcxx/control.cpp b/src/model/dfcxx/lib/dfcxx/control.cpp index bf24260..d146248 100644 --- a/src/model/dfcxx/lib/dfcxx/control.cpp +++ b/src/model/dfcxx/lib/dfcxx/control.cpp @@ -11,23 +11,18 @@ namespace dfcxx { -Control::Control(Graph &graph, TypeBuilder &typeBuilder, VarBuilder &varBuilder, - KernStorage &storage) : graph(graph), - helper(graph, typeBuilder, - varBuilder, storage), - varBuilder(varBuilder), - storage(storage) {} +Control::Control(KernMeta &meta) : meta(meta) {} DFVariable Control::mux(DFVariable ctrl, std::initializer_list args) { const DFVariable *argsData = args.begin(); unsigned argsCount = args.size(); - DFVariable var = helper.varBuilder.buildMuxCopy(argsData[0], helper); - storage.addVariable(var); - graph.addNode(var, OpType::MUX, NodeData{.muxId = 0}); - graph.addChannel(ctrl, var, 0, false); + auto *var = meta.varBuilder.buildClone(argsData[0]); + meta.storage.addVariable(var); + meta.graph.addNode(var, OpType::MUX, NodeData{.muxId = 0}); + meta.graph.addChannel(ctrl, var, 0, false); for (unsigned i = 0; i < argsCount; ++i) { - graph.addChannel(argsData[i], var, i + 1, false); + meta.graph.addChannel(argsData[i], var, i + 1, false); } return var; } diff --git a/src/model/dfcxx/lib/dfcxx/graph.cpp b/src/model/dfcxx/lib/dfcxx/graph.cpp index 5ae866d..1d453bb 100644 --- a/src/model/dfcxx/lib/dfcxx/graph.cpp +++ b/src/model/dfcxx/lib/dfcxx/graph.cpp @@ -12,20 +12,43 @@ namespace dfcxx { +const std::unordered_set& Graph::getNodes() const { + return nodes; +} + +const std::unordered_set& Graph::getStartNodes() const { + return startNodes; +} + +const std::unordered_map> &Graph::getInputs() const { + return inputs; +} + +const std::unordered_map> &Graph::getOutputs() const { + return outputs; +} + +const std::unordered_map &Graph::getConnections() const { + return connections; +} + Node Graph::findNode(DFVariableImpl *var) { return *std::find_if(nodes.begin(), nodes.end(), [&](const Node &node) { return node.var == var; }); } void Graph::addNode(DFVariableImpl *var, OpType type, NodeData data) { - nodes.emplace(var, type, data); + auto node = nodes.emplace(var, type, data); if (type == IN || type == CONST) { startNodes.emplace(var, type, data); } -} - -void Graph::addNode(const DFVariable &var, OpType type, NodeData data) { - addNode(var.getImpl(), type, data); + // The following lines create empty channel vectors + // for new nodes. This allows to use .at() on unconnected + // nodes without getting an exception. + (void)inputs[*(node.first)]; + (void)outputs[*(node.first)]; } void Graph::addChannel(DFVariableImpl *source, DFVariableImpl *target, @@ -41,9 +64,4 @@ void Graph::addChannel(DFVariableImpl *source, DFVariableImpl *target, } } -void Graph::addChannel(const DFVariable &source, const DFVariable &target, - unsigned opInd, bool connect) { - addChannel(source.getImpl(), target.getImpl(), opInd, connect); -} - } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index 4d6b206..fa2e6ae 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -21,12 +21,16 @@ Kernel::Kernel() : meta(), io(meta), offset(meta), constant(meta), control(meta) {} DFType Kernel::dfUInt(uint8_t bits) { - auto *type = meta.typeBuilder.buildFixed(SignMode::UNSIGNED, bits, 0); + auto *type = meta.typeBuilder.buildFixed(FixedType::SignMode::UNSIGNED, + bits, + 0); return meta.storage.addType(type); } DFType Kernel::dfInt(uint8_t bits) { - auto *type = meta.typeBuilder.buildFixed(SignMode::SIGNED, bits, 0); + auto *type = meta.typeBuilder.buildFixed(FixedType::SignMode::SIGNED, + bits, + 0); return meta.storage.addType(type); } @@ -40,6 +44,9 @@ DFType Kernel::dfBool() { return meta.storage.addType(type); } +const Graph& Kernel::getGraph() const { + return meta.graph; +} bool Kernel::compile(const DFLatencyConfig &config, const std::vector &outputPaths, @@ -80,12 +87,9 @@ bool Kernel::compile(const DFLatencyConfig &config, bool Kernel::simulate(const std::string &inDataPath, - const std::string &outFilePath, - bool intermediateResults) { - std::vector sorted = topSort(graph.startNodes, - graph.outputs, - graph.nodes.size()); - DFCXXSimulator sim(sorted, graph.inputs, intermediateResults); + const std::string &outFilePath) { + std::vector sorted = topSort(meta.graph); + DFCXXSimulator sim(sorted, meta.graph.getInputs()); std::ifstream input(inDataPath, std::ios::in); if (!input || input.bad() || input.eof() || input.fail() || !input.is_open()) { return false; diff --git a/src/model/dfcxx/lib/dfcxx/offset.cpp b/src/model/dfcxx/lib/dfcxx/offset.cpp index 96a4b9b..fdc47be 100644 --- a/src/model/dfcxx/lib/dfcxx/offset.cpp +++ b/src/model/dfcxx/lib/dfcxx/offset.cpp @@ -15,7 +15,8 @@ Offset::Offset(KernMeta &meta) : meta(meta) {} DFVariable Offset::operator()(DFVariable &stream, int64_t offset) { if (!stream.isStream()) { throw std::exception(); } - auto *var = meta.varBuilder.buildStream("", IODirection::NONE, + auto *var = meta.varBuilder.buildStream("", + DFVariableImpl::IODirection::NONE, meta, stream.getType()); meta.storage.addVariable(var); meta.graph.addNode(var, OpType::OFFSET, NodeData{.offset = offset}); diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 6fe8735..88f4487 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -6,10 +6,9 @@ namespace dfcxx { -DFCXXSimulator::DFCXXSimulator(std::vector &nodes, Inputs &inputs, - bool intermediateResults) : - nodes(nodes), inputs(inputs), - intermediateResults(intermediateResults) {} +DFCXXSimulator::DFCXXSimulator(std::vector &nodes, + const Inputs &inputs) : nodes(nodes), + inputs(inputs) {} @@ -48,7 +47,7 @@ void DFCXXSimulator::processOutput(RecordedValues &vals, Node &node, IOVars &output, uint64_t ind) { auto name = std::string(DFVariable(node.var).getName()); // Take output's only connection and assign the existing source value. - vals[node] = vals[inputs[node][0].source]; + vals[node] = vals[inputs.at(node)[0].source]; output[name][ind] = vals[node]; } @@ -57,8 +56,8 @@ void DFCXXSimulator::processConst(RecordedValues &vals, Node &node) { } void DFCXXSimulator::processMux(RecordedValues &vals, Node &node) { - auto muxedValue = vals[inputs[node][node.data.muxId].source]; - vals[node] = vals[inputs[node][muxedValue + 1].source]; + auto muxedValue = vals[inputs.at(node)[node.data.muxId].source]; + vals[node] = vals[inputs.at(node)[muxedValue + 1].source]; } template <> @@ -67,16 +66,16 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left + right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] + vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] + vals[inputs.at(node)[1].source]; } } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); - double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); double result = left + right; vals[node] = *(reinterpret_cast(&result)); } @@ -88,16 +87,16 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left - right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] - vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] - vals[inputs.at(node)[1].source]; } } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); - double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); double result = left - right; vals[node] = *(reinterpret_cast(&result)); } @@ -109,16 +108,16 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left * right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] * vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] * vals[inputs.at(node)[1].source]; } } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); - double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); double result = left * right; vals[node] = *(reinterpret_cast(&result)); } @@ -130,16 +129,16 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left / right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] / vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] / vals[inputs.at(node)[1].source]; } } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); - double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); double result = left / right; vals[node] = *(reinterpret_cast(&result)); } @@ -151,12 +150,12 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left & right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] & vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] & vals[inputs.at(node)[1].source]; } } // No AND for floats. @@ -168,12 +167,12 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left | right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] | vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] | vals[inputs.at(node)[1].source]; } } // No OR for floats. @@ -185,12 +184,12 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left ^ right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] ^ vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] ^ vals[inputs.at(node)[1].source]; } } // No XOR for floats. @@ -199,7 +198,7 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, template <> void DFCXXSimulator::processUnaryOp(RecordedValues &vals, Node &node) { - vals[node] = ~(vals[inputs[node][0].source]); + vals[node] = ~(vals[inputs.at(node)[0].source]); } template <> @@ -207,11 +206,11 @@ void DFCXXSimulator::processUnaryOp(RecordedValues &vals, Node &node) { DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); int64_t result = -left; vals[node] = *(reinterpret_cast(&result)); } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); double result = -left; vals[node] = *(reinterpret_cast(&result)); } @@ -223,16 +222,16 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left < right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] < vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] < vals[inputs.at(node)[1].source]; } } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); - double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); double result = left < right; vals[node] = *(reinterpret_cast(&result)); } @@ -244,16 +243,16 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left <= right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] <= vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] <= vals[inputs.at(node)[1].source]; } } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); - double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); double result = left <= right; vals[node] = *(reinterpret_cast(&result)); } @@ -265,16 +264,16 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left > right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] > vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] > vals[inputs.at(node)[1].source]; } } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); - double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); double result = left > right; vals[node] = *(reinterpret_cast(&result)); } @@ -286,16 +285,16 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs[node][1].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); int64_t result = left >= right; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] >= vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] >= vals[inputs.at(node)[1].source]; } } else { - double left = *(reinterpret_cast(&vals[inputs[node][0].source])); - double right = *(reinterpret_cast(&vals[inputs[node][1].source])); + double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); double result = left >= right; vals[node] = *(reinterpret_cast(&result)); } @@ -304,24 +303,24 @@ void DFCXXSimulator::processBinaryOp(RecordedValues &vals, template <> void DFCXXSimulator::processBinaryOp(RecordedValues &vals, Node &node) { - vals[node] = vals[inputs[node][0].source] == vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] == vals[inputs.at(node)[1].source]; } template <> void DFCXXSimulator::processBinaryOp(RecordedValues &vals, Node &node) { - vals[node] = vals[inputs[node][0].source] != vals[inputs[node][1].source]; + vals[node] = vals[inputs.at(node)[0].source] != vals[inputs.at(node)[1].source]; } void DFCXXSimulator::processShiftLeft(RecordedValues &vals, Node &node) { DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); int64_t result = left << node.data.bitShift; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] << node.data.bitShift; + vals[node] = vals[inputs.at(node)[0].source] << node.data.bitShift; } } // No left bit shift for floats. @@ -331,21 +330,16 @@ void DFCXXSimulator::processShiftRight(RecordedValues &vals, Node &node) { DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs[node][0].source])); + int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); int64_t result = left >> node.data.bitShift; vals[node] = *(reinterpret_cast(&result)); } else { - vals[node] = vals[inputs[node][0].source] >> node.data.bitShift; + vals[node] = vals[inputs.at(node)[0].source] >> node.data.bitShift; } } // No right bit shift for floats. } -bool DFCXXSimulator::processOp(RecordedValues &vals, Node &node, - IOVars &input, uint64_t ind) { - if (intermediateResults) {} -} - bool DFCXXSimulator::runSim(IOVars &input, IOVars &output, uint64_t count) { @@ -356,9 +350,6 @@ bool DFCXXSimulator::runSim(IOVars &input, RecordedValues vals; for (uint64_t i = 0; i < count; ++i) { for (Node &node : nodes) { - if (!processOp(vals, node, i, input, output)) { - return false; - } switch (node.type) { case OFFSET: return false; // TODO: Add offset support in the future. diff --git a/src/model/dfcxx/lib/dfcxx/typebuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/typebuilders/builder.cpp index 644bc7b..a675646 100644 --- a/src/model/dfcxx/lib/dfcxx/typebuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/typebuilders/builder.cpp @@ -10,13 +10,14 @@ namespace dfcxx { -DFTypeImpl *TypeBuilder::buildFixed(dfcxx::SignMode mode, uint8_t intBits, +DFTypeImpl *TypeBuilder::buildFixed(FixedType::SignMode mode, + uint8_t intBits, uint8_t fracBits) { return new FixedType(mode, intBits, fracBits); } DFTypeImpl *TypeBuilder::buildBool() { - return buildFixed(dfcxx::SignMode::UNSIGNED, 1, 0); + return buildFixed(FixedType::SignMode::UNSIGNED, 1, 0); } DFTypeImpl *TypeBuilder::buildFloat(uint8_t expBits, uint8_t fracBits) { diff --git a/src/model/dfcxx/lib/dfcxx/types/fixed.cpp b/src/model/dfcxx/lib/dfcxx/types/fixed.cpp index 4532474..b9095b9 100644 --- a/src/model/dfcxx/lib/dfcxx/types/fixed.cpp +++ b/src/model/dfcxx/lib/dfcxx/types/fixed.cpp @@ -14,7 +14,7 @@ FixedType::FixedType(SignMode mode, uint8_t intBits, uint8_t fracBits) : mode(mode), intBits(intBits), fracBits(fracBits) {} -SignMode FixedType::getSign() const { +FixedType::SignMode FixedType::getSign() const { return mode; } diff --git a/src/model/dfcxx/lib/dfcxx/types/type.cpp b/src/model/dfcxx/lib/dfcxx/types/type.cpp index 3925f27..112d550 100644 --- a/src/model/dfcxx/lib/dfcxx/types/type.cpp +++ b/src/model/dfcxx/lib/dfcxx/types/type.cpp @@ -24,7 +24,7 @@ bool DFTypeImpl::isFloat() const { DFType::DFType(DFTypeImpl *impl) : impl(impl) {} -DFType::operator DFTypeImpl*() { +DFType::operator DFTypeImpl*() const { return impl; } diff --git a/src/model/dfcxx/lib/dfcxx/utils.cpp b/src/model/dfcxx/lib/dfcxx/utils.cpp index 329f41c..01e078a 100644 --- a/src/model/dfcxx/lib/dfcxx/utils.cpp +++ b/src/model/dfcxx/lib/dfcxx/utils.cpp @@ -10,16 +10,16 @@ namespace dfcxx { -std::vector topSort(std::unordered_set startNodes, - std::unordered_map> outs, - size_t nodesCount) { +std::vector topSort(const Graph &graph) { + size_t nodesCount = graph.getNodes().size(); + auto &outs = graph.getOutputs(); + std::vector result(nodesCount); std::unordered_map checked; std::stack stack; - for (Node node: startNodes) { + for (Node node: graph.getStartNodes()) { stack.push(node); checked[node] = 0; } @@ -27,11 +27,11 @@ std::vector topSort(std::unordered_set startNodes, size_t i = nodesCount - 1; while (!stack.empty()) { Node node = stack.top(); - size_t count = outs[node].size(); + size_t count = outs.at(node).size(); size_t curr; bool flag = true; for (curr = checked[node]; flag && curr < count; ++curr) { - Channel next = outs[node][curr]; + Channel next = outs.at(node)[curr]; if (!checked[next.target]) { stack.push(next.target); flag = false; diff --git a/src/model/dfcxx/lib/dfcxx/varbuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/varbuilders/builder.cpp index 7f396b9..4d37bfd 100644 --- a/src/model/dfcxx/lib/dfcxx/varbuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/varbuilders/builder.cpp @@ -11,38 +11,27 @@ namespace dfcxx { DFVariableImpl *VarBuilder::buildStream(const std::string &name, - IODirection direction, + DFVariableImpl::IODirection direction, KernMeta &meta, DFTypeImpl *type) { return new DFStream(name, direction, meta, type); } DFVariableImpl *VarBuilder::buildScalar(const std::string &name, - IODirection direction, + DFVariableImpl::IODirection direction, KernMeta &meta, DFTypeImpl *type) { - return new DFScalar(name, direction, helper, type); + return new DFScalar(name, direction, meta, type); } DFVariableImpl *VarBuilder::buildConstant(KernMeta &meta, DFTypeImpl *type, - ConstantTypeKind kind, - ConstantValue value) { - return new DFConstant(helper, type, kind, value); + DFConstant::Value value) { + return new DFConstant(meta, type, value); } -DFVariableImpl *VarBuilder::buildMuxCopy(DFVariableImpl *var, KernMeta &meta) { - if (var->isConstant()) { - return buildConstant(meta, var->getType(), - ((DFConstant *) var)->getKind(), - ConstantValue{}); - } else if (var->isScalar()) { - return buildScalar("", IODirection::NONE, meta, - var->getType()); - } else /* if (var.isStream()) */ { - return buildStream("", IODirection::NONE, meta, - var->getType()); - } +DFVariableImpl *VarBuilder::buildClone(DFVariableImpl *var) { + return var->clone(); } } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/vars/constant.cpp b/src/model/dfcxx/lib/dfcxx/vars/constant.cpp index c92bdbc..c07a81d 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/constant.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/constant.cpp @@ -6,18 +6,28 @@ // //===----------------------------------------------------------------------===// -#include "dfcxx/graph.h" -#include "dfcxx/kernstorage.h" -#include "dfcxx/types/types.h" -#include "dfcxx/varbuilders/builder.h" +#include "dfcxx/kernmeta.h" #include "dfcxx/vars/constant.h" namespace dfcxx { -DFConstant::DFConstant(KernMeta &meta, DFTypeImpl *type, - ConstantTypeKind kind, ConstantValue value) : +DFConstant::DFConstant(KernMeta &meta, DFTypeImpl *type, Value value) : DFVariableImpl("", IODirection::NONE, meta), - type(*type), kind(kind), value(value) {} + type(*type), value(value) { + if (this->type.isFixed()) { + if (((FixedType &) this->type).isSigned()) { + kind = TypeKind::INT; + } else { + kind = TypeKind::UINT; + } + } else { + kind = TypeKind::FLOAT; + } +} + +DFVariableImpl *DFConstant::clone() const { + return new DFConstant(meta, &type, value); +} DFTypeImpl *DFConstant::getType() { return &type; @@ -26,7 +36,7 @@ DFTypeImpl *DFConstant::getType() { DFVariableImpl *DFConstant::operator+(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -39,7 +49,7 @@ DFVariableImpl *DFConstant::operator+(DFVariableImpl &rhs) { val.double_ = value.double_ + casted.value.double_; break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } @@ -53,7 +63,7 @@ DFVariableImpl *DFConstant::operator+(DFVariableImpl &rhs) { DFVariableImpl *DFConstant::operator-(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -66,7 +76,7 @@ DFVariableImpl *DFConstant::operator-(DFVariableImpl &rhs) { val.double_ = value.double_ - casted.value.double_; break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } @@ -80,7 +90,7 @@ DFVariableImpl *DFConstant::operator-(DFVariableImpl &rhs) { DFVariableImpl *DFConstant::operator*(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -93,7 +103,7 @@ DFVariableImpl *DFConstant::operator*(DFVariableImpl &rhs) { val.double_ = value.double_ * casted.value.double_; break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } @@ -107,7 +117,7 @@ DFVariableImpl *DFConstant::operator*(DFVariableImpl &rhs) { DFVariableImpl *DFConstant::operator/(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -120,7 +130,7 @@ DFVariableImpl *DFConstant::operator/(DFVariableImpl &rhs) { val.double_ = value.double_ / casted.value.double_; break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } @@ -134,7 +144,7 @@ DFVariableImpl *DFConstant::operator/(DFVariableImpl &rhs) { DFVariableImpl *DFConstant::operator&(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -148,7 +158,7 @@ DFVariableImpl *DFConstant::operator&(DFVariableImpl &rhs) { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } @@ -162,7 +172,7 @@ DFVariableImpl *DFConstant::operator&(DFVariableImpl &rhs) { DFVariableImpl *DFConstant::operator|(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -176,7 +186,7 @@ DFVariableImpl *DFConstant::operator|(DFVariableImpl &rhs) { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } @@ -190,7 +200,7 @@ DFVariableImpl *DFConstant::operator|(DFVariableImpl &rhs) { DFVariableImpl *DFConstant::operator^(DFVariableImpl &rhs) { DFVariableImpl *newVar; if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -204,7 +214,7 @@ DFVariableImpl *DFConstant::operator^(DFVariableImpl &rhs) { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); } @@ -217,7 +227,7 @@ DFVariableImpl *DFConstant::operator^(DFVariableImpl &rhs) { DFVariableImpl *DFConstant::operator!() { DFVariableImpl *newVar; - ConstantValue val{}; + Value val{}; switch (kind) { case INT: val.int_ = ~value.int_; @@ -230,7 +240,7 @@ DFVariableImpl *DFConstant::operator!() { // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::NOT, NodeData{}); meta.graph.addChannel(this, newVar, 0, false); @@ -239,7 +249,7 @@ DFVariableImpl *DFConstant::operator!() { DFVariableImpl *DFConstant::operator-() { DFVariableImpl *newVar; - ConstantValue val{}; + Value val{}; switch (kind) { case INT: val.int_ = -value.int_; @@ -251,7 +261,7 @@ DFVariableImpl *DFConstant::operator-() { val.double_ = -value.double_; break; } - newVar = meta.varBuilder.buildConstant(meta, &type, kind, val); + newVar = meta.varBuilder.buildConstant(meta, &type, val); meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::NEG, NodeData{}); meta.graph.addChannel(this, newVar, 0, false); @@ -262,7 +272,7 @@ DFVariableImpl *DFConstant::operator<(DFVariableImpl &rhs) { DFVariableImpl *newVar; DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -276,11 +286,11 @@ DFVariableImpl *DFConstant::operator<(DFVariableImpl &rhs) { break; } newVar = meta.varBuilder.buildConstant(meta, - *newType, - kind, val); + newType, + val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - *newType); + newType); } meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::LESS, NodeData{}); @@ -293,7 +303,7 @@ DFVariableImpl *DFConstant::operator<=(DFVariableImpl &rhs) { DFVariableImpl *newVar; DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -307,11 +317,11 @@ DFVariableImpl *DFConstant::operator<=(DFVariableImpl &rhs) { break; } newVar = meta.varBuilder.buildConstant(meta, - *newType, - kind, val); + newType, + val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - *newType); + newType); } meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::LESSEQ, NodeData{}); @@ -324,7 +334,7 @@ DFVariableImpl *DFConstant::operator>(DFVariableImpl &rhs) { DFVariableImpl *newVar; DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -338,11 +348,11 @@ DFVariableImpl *DFConstant::operator>(DFVariableImpl &rhs) { break; } newVar = meta.varBuilder.buildConstant(meta, - *newType, - kind, val); + newType, + val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - *newType); + newType); } meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::GREATER, NodeData{}); @@ -355,7 +365,7 @@ DFVariableImpl *DFConstant::operator>=(DFVariableImpl &rhs) { DFVariableImpl *newVar; DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -369,11 +379,11 @@ DFVariableImpl *DFConstant::operator>=(DFVariableImpl &rhs) { break; } newVar = meta.varBuilder.buildConstant(meta, - *newType, - kind, val); + newType, + val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - *newType); + newType); } meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::GREATEREQ, NodeData{}); @@ -386,7 +396,7 @@ DFVariableImpl *DFConstant::operator==(DFVariableImpl &rhs) { DFVariableImpl *newVar; DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -400,11 +410,11 @@ DFVariableImpl *DFConstant::operator==(DFVariableImpl &rhs) { break; } newVar = meta.varBuilder.buildConstant(meta, - *newType, - kind, val); + newType, + val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - *newType); + newType); } meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::EQ, NodeData{}); @@ -417,7 +427,7 @@ DFVariableImpl *DFConstant::operator!=(DFVariableImpl &rhs) { DFVariableImpl *newVar; DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); if (rhs.isConstant()) { - ConstantValue val{}; + Value val{}; DFConstant &casted = (DFConstant &) (rhs); switch (kind) { case INT: @@ -431,11 +441,11 @@ DFVariableImpl *DFConstant::operator!=(DFVariableImpl &rhs) { break; } newVar = meta.varBuilder.buildConstant(meta, - *newType, - kind, val); + newType, + val); } else { newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - *newType); + newType); } meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::NEQ, NodeData{}); @@ -446,7 +456,7 @@ DFVariableImpl *DFConstant::operator!=(DFVariableImpl &rhs) { DFVariableImpl *DFConstant::operator<<(uint8_t bits) { DFVariableImpl *newVar; - ConstantValue val{}; + Value val{}; switch (kind) { case INT: val.int_ = value.int_ << bits; @@ -460,8 +470,8 @@ DFVariableImpl *DFConstant::operator<<(uint8_t bits) { break; } DFTypeImpl *newType = meta.storage.addType( - meta.typeBuilder.buildShiftedType(type, bits)); - newVar = meta.varBuilder.buildConstant(meta, newType, kind, val); + meta.typeBuilder.buildShiftedType(&type, bits)); + newVar = meta.varBuilder.buildConstant(meta, newType, val); meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); meta.graph.addChannel(this, newVar, 0, false); @@ -470,7 +480,7 @@ DFVariableImpl *DFConstant::operator<<(uint8_t bits) { DFVariableImpl *DFConstant::operator>>(uint8_t bits) { DFVariableImpl *newVar; - ConstantValue val{}; + Value val{}; switch (kind) { case INT: val.int_ = value.int_ >> bits; @@ -484,15 +494,15 @@ DFVariableImpl *DFConstant::operator>>(uint8_t bits) { break; } DFTypeImpl *newType = meta.storage.addType( - meta.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); - newVar = meta.varBuilder.buildConstant(meta, newType, kind, val); + meta.typeBuilder.buildShiftedType(&type, int8_t(bits) * -1)); + newVar = meta.varBuilder.buildConstant(meta, newType, val); meta.storage.addVariable(newVar); meta.graph.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); meta.graph.addChannel(this, newVar, 0, false); return newVar; } -ConstantTypeKind DFConstant::getKind() const { +DFConstant::TypeKind DFConstant::getKind() const { return kind; } diff --git a/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp b/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp index e32992a..4097ba8 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp @@ -6,9 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "dfcxx/graph.h" -#include "dfcxx/kernstorage.h" -#include "dfcxx/varbuilders/builder.h" +#include "dfcxx/kernmeta.h" #include "dfcxx/vars/scalar.h" namespace dfcxx { @@ -17,6 +15,10 @@ DFScalar::DFScalar(const std::string &name, IODirection direction, KernMeta &meta, DFTypeImpl *type) : DFVariableImpl(name, direction, meta), type(*type) {} +DFVariableImpl *DFScalar::clone() const { + return new DFScalar(name, direction, meta, &type); +} + DFTypeImpl *DFScalar::getType() { return &type; } @@ -177,7 +179,7 @@ DFVariableImpl *DFScalar::operator!=(DFVariableImpl &rhs) { DFVariableImpl *DFScalar::operator<<(uint8_t bits) { DFTypeImpl *newType = meta.storage.addType( - meta.typeBuilder.buildShiftedType(type, bits)); + meta.typeBuilder.buildShiftedType(&type, bits)); DFVariableImpl *newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); meta.storage.addVariable(newVar); @@ -188,7 +190,7 @@ DFVariableImpl *DFScalar::operator<<(uint8_t bits) { DFVariableImpl *DFScalar::operator>>(uint8_t bits) { DFTypeImpl *newType = meta.storage.addType( - meta.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); + meta.typeBuilder.buildShiftedType(&type, int8_t(bits) * -1)); DFVariableImpl *newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); meta.storage.addVariable(newVar); diff --git a/src/model/dfcxx/lib/dfcxx/vars/stream.cpp b/src/model/dfcxx/lib/dfcxx/vars/stream.cpp index 24822c1..fda20f6 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/stream.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/stream.cpp @@ -6,9 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "dfcxx/graph.h" -#include "dfcxx/kernstorage.h" -#include "dfcxx/varbuilders/builder.h" +#include "dfcxx/kernmeta.h" #include "dfcxx/vars/stream.h" namespace dfcxx { @@ -17,6 +15,10 @@ DFStream::DFStream(const std::string &name, IODirection direction, KernMeta &meta, DFTypeImpl *type) : DFVariableImpl(name, direction, meta), type(*type) {} +DFVariableImpl *DFStream::clone() const { + return new DFStream(name, direction, meta, &type); +} + DFTypeImpl *DFStream::getType() { return &type; } @@ -177,7 +179,7 @@ DFVariableImpl *DFStream::operator!=(DFVariableImpl &rhs) { DFVariableImpl *DFStream::operator<<(uint8_t bits) { DFTypeImpl *newType = meta.storage.addType( - meta.typeBuilder.buildShiftedType(type, bits)); + meta.typeBuilder.buildShiftedType(&type, bits)); DFVariableImpl *newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); meta.storage.addVariable(newVar); @@ -188,7 +190,7 @@ DFVariableImpl *DFStream::operator<<(uint8_t bits) { DFVariableImpl *DFStream::operator>>(uint8_t bits) { DFTypeImpl *newType = meta.storage.addType( - meta.typeBuilder.buildShiftedType(type, int8_t(bits) * -1)); + meta.typeBuilder.buildShiftedType(&type, int8_t(bits) * -1)); DFVariableImpl *newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); meta.storage.addVariable(newVar); diff --git a/src/model/dfcxx/lib/dfcxx/vars/var.cpp b/src/model/dfcxx/lib/dfcxx/vars/var.cpp index 71d8405..e413ef5 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/var.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/var.cpp @@ -6,14 +6,13 @@ // //===----------------------------------------------------------------------===// -#include "dfcxx/graph.h" -#include "dfcxx/kernstorage.h" -#include "dfcxx/varbuilders/builder.h" +#include "dfcxx/kernmeta.h" #include "dfcxx/vars/var.h" namespace dfcxx { -DFVariableImpl::DFVariableImpl(const std::string &name, IODirection direction, +DFVariableImpl::DFVariableImpl(const std::string &name, + IODirection direction, KernMeta &meta) : name(name), direction(direction), meta(meta) {} @@ -22,10 +21,14 @@ std::string_view DFVariableImpl::getName() const { return name; } -IODirection DFVariableImpl::getDirection() const { +DFVariableImpl::IODirection DFVariableImpl::getDirection() const { return direction; } +const KernMeta &DFVariableImpl::getMeta() const { + return meta; +} + bool DFVariableImpl::isStream() const { return false; } @@ -39,12 +42,12 @@ bool DFVariableImpl::isConstant() const { } void DFVariableImpl::connect(DFVariableImpl *connectee) { - meta.addChannel(connectee, this, 0, true); + meta.graph.addChannel(connectee, this, 0, true); } DFVariable::DFVariable(DFVariableImpl *impl) : impl(impl) {} -DFVariable::operator DFVariableImpl*() { +DFVariable::operator DFVariableImpl*() const { return impl; } @@ -56,14 +59,10 @@ std::string_view DFVariable::getName() const { return impl->getName(); } -IODirection DFVariable::getDirection() const { +DFVariableImpl::IODirection DFVariable::getDirection() const { return impl->getDirection(); } -const KernMeta &DFVariable::getMeta() const { - return impl->getMeta(); -} - DFType DFVariable::getType() const { return DFType(impl->getType()); } diff --git a/src/options.h b/src/options.h index d52556a..640c95e 100644 --- a/src/options.h +++ b/src/options.h @@ -43,7 +43,6 @@ #define SIM_ID_JSON "sim" #define SIM_IN_JSON "in" -#define SIM_INTERMEDIATE_RESULTS_JSON "intermediate" #define SIM_OUT_JSON "out" //===----------------------------------------------------------------------===// @@ -62,7 +61,6 @@ #define OUT_FIRRTL_ARG CLI_ARG("out-firrtl") #define SIM_IN_ARG CLI_ARG("in") -#define SIM_INTERMEDIATE_RESULTS_FLAG CLI_FLAG("i") #define SIM_OUT_ARG CLI_ARG("out") //===----------------------------------------------------------------------===// @@ -277,15 +275,11 @@ struct SimOptions final : public AppOptions { SimOptions(AppOptions &parent): AppOptions(parent, SIM_CMD, "DFCxx simulation") { - //options->formatter(std::make_shared()); // Named options. options->add_option(SIM_IN_ARG, inFilePath, "Simulation input data path")->capture_default_str(); - schedGroup->add_flag(SIM_INTERMEDIATE_RESULTS_FLAG, - intermediateResults, - "Dump intermediate computations as well")->capture_default_str(); options->add_option(SIM_OUT_ARG, outFilePath, "Simulation results output path")->capture_default_str(); @@ -293,12 +287,10 @@ struct SimOptions final : public AppOptions { void fromJson(Json json) override { get(json, SIM_IN_JSON, inFilePath); - get(json, SIM_INTERMEDIATE_RESULTS_JSON, intermediateResults); get(json, SIM_OUT_JSON, outFilePath); } std::string inFilePath; - bool intermediateResults; std::string outFilePath; std::vector files; }; From 596a93658f2c9b67dd20efbd36d97f68472378a2 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Thu, 22 Aug 2024 20:50:10 +0300 Subject: [PATCH 13/21] License header for simulator.cpp . --- src/model/dfcxx/lib/dfcxx/simulator.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 88f4487..e7e3cd8 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -1,3 +1,11 @@ +//===----------------------------------------------------------------------===// +// +// Part of the Utopia HLS Project, under the Apache License v2.0 +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 ISP RAS (http://www.ispras.ru) +// +//===----------------------------------------------------------------------===// + #include "dfcxx/simulator.h" #include "dfcxx/types/types.h" #include "dfcxx/vars/vars.h" From df531b02211fc8ca1b43e181c433666105633aef Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Mon, 26 Aug 2024 03:43:40 +0300 Subject: [PATCH 14/21] DFCxx operation simulation handling logic revamped. --- src/model/dfcxx/includeDev/dfcxx/simulator.h | 32 +- src/model/dfcxx/lib/dfcxx/simulator.cpp | 462 +++++++------------ 2 files changed, 175 insertions(+), 319 deletions(-) diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index a9cdee0..e1fde42 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -10,6 +10,7 @@ #define DFCXX_SIMULATOR_H #include "dfcxx/graph.h" +#include "dfcxx/node.h" #include #include @@ -31,6 +32,12 @@ typedef std::unordered_map> Inputs; typedef std::unordered_map RecordedValues; +typedef bool (*OpSimulationFunc)(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind); + +typedef std::unordered_map OpSimulationFuncs; + class DFCXXSimulator { public: DFCXXSimulator(std::vector &nodes, @@ -38,26 +45,17 @@ class DFCXXSimulator { bool simulate(std::ifstream &in, std::ofstream &out); private: - uint64_t readInputData(std::ifstream &in, IOVars &inputMapping); - bool runSim(IOVars &input, IOVars &output, uint64_t count); - bool writeOutput(std::ofstream &out, IOVars &output, uint64_t count); - - void processInput(RecordedValues &vals, Node &node, - IOVars &input, uint64_t ind); - void processOutput(RecordedValues &vals, Node &node, - IOVars &output, uint64_t ind); - void processConst(RecordedValues &vals, Node &node); - void processMux(RecordedValues &vals, Node &node); - template - void processBinaryOp(RecordedValues &vals, Node &node); - template - void processUnaryOp(RecordedValues &vals, Node &node); - void processShiftLeft(RecordedValues &vals, Node &node); - void processShiftRight(RecordedValues &vals, Node &node); + uint64_t readInput(std::ifstream &in, IOVars &inData); + bool runSim(IOVars &inData, IOVars &outData, uint64_t count); + + bool processOp(RecordedValues &vals, const Node &node, + const IOVars &inData, IOVars &outData, uint64_t ind); + + bool writeOutput(std::ofstream &out, const IOVars &outData, uint64_t count); std::vector &nodes; const Inputs &inputs; - bool intermediateResults; + const OpSimulationFuncs funcs; }; } // namespace dfcxx diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index e7e3cd8..d319231 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -14,14 +14,8 @@ namespace dfcxx { -DFCXXSimulator::DFCXXSimulator(std::vector &nodes, - const Inputs &inputs) : nodes(nodes), - inputs(inputs) {} - - - -uint64_t DFCXXSimulator::readInputData(std::ifstream &in, - IOVars &inputMapping) { +uint64_t DFCXXSimulator::readInput(std::ifstream &in, + IOVars &inData) { uint64_t ind = 0; std::string line; bool atLeastOne = false; @@ -38,318 +32,204 @@ uint64_t DFCXXSimulator::readInputData(std::ifstream &in, return 0; } atLeastOne = true; - inputMapping[line.substr(0, spaceInd)][ind] = + inData[line.substr(0, spaceInd)][ind] = std::stoul(line.substr(spaceInd + 1), 0, 16); } // It is assumed that at least one data block exists. return atLeastOne ? (ind + 1) : 0; } -void DFCXXSimulator::processInput(RecordedValues &vals, Node &node, - IOVars &input, uint64_t ind) { +static bool processInput(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind) { auto name = std::string(DFVariable(node.var).getName()); - vals[node] = input[name][ind]; + vals[node] = inData.at(name)[ind]; + return true; } -void DFCXXSimulator::processOutput(RecordedValues &vals, Node &node, - IOVars &output, uint64_t ind) { +static bool processOutput(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind) { auto name = std::string(DFVariable(node.var).getName()); // Take output's only connection and assign the existing source value. vals[node] = vals[inputs.at(node)[0].source]; - output[name][ind] = vals[node]; + outData[name][ind] = vals[node]; + return true; } -void DFCXXSimulator::processConst(RecordedValues &vals, Node &node) { +static bool processConst(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind) { vals[node] = ((DFConstant *) node.var)->getUInt(); + return true; } -void DFCXXSimulator::processMux(RecordedValues &vals, Node &node) { +static bool processMux(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind) { auto muxedValue = vals[inputs.at(node)[node.data.muxId].source]; vals[node] = vals[inputs.at(node)[muxedValue + 1].source]; + return true; } -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left + right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] + vals[inputs.at(node)[1].source]; - } - } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - double result = left + right; - vals[node] = *(reinterpret_cast(&result)); - } +#define GENERIC_FUNC_NAME(OP_NAME) process##OP_NAME##Name +#define PROCESS_GENERIC_BINARY_OP_FUNC(OP_NAME, OP) \ +static bool GENERIC_FUNC_NAME(OP_NAME)(RecordedValues &vals, \ + const Node &node, \ + const Inputs &inputs, \ + const IOVars &inData, \ + IOVars &outData, \ + uint64_t ind) { \ + DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); \ + if (type->isFixed()) { \ + if (((FixedType*) type)->isSigned()) { \ + int64_t left = \ + *(reinterpret_cast(&vals[inputs.at(node)[0].source])); \ + int64_t right = \ + *(reinterpret_cast(&vals[inputs.at(node)[1].source])); \ + int64_t result = left OP right; \ + vals[node] = \ + *(reinterpret_cast(&result)); \ + } else { \ + vals[node] = \ + vals[inputs.at(node)[0].source] OP vals[inputs.at(node)[1].source]; \ + } \ + } else if (type->isFloat()) { \ + double left = \ + *(reinterpret_cast(&vals[inputs.at(node)[0].source])); \ + double right = \ + *(reinterpret_cast(&vals[inputs.at(node)[1].source])); \ + double result = left OP right; \ + vals[node] = \ + *(reinterpret_cast(&result)); \ + } else { \ + return false; \ + } \ + return true; \ } -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left - right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] - vals[inputs.at(node)[1].source]; - } - } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - double result = left - right; - vals[node] = *(reinterpret_cast(&result)); - } -} +PROCESS_GENERIC_BINARY_OP_FUNC(Add, +) -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left * right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] * vals[inputs.at(node)[1].source]; - } - } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - double result = left * right; - vals[node] = *(reinterpret_cast(&result)); - } -} +PROCESS_GENERIC_BINARY_OP_FUNC(Sub, -) -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left / right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] / vals[inputs.at(node)[1].source]; - } - } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - double result = left / right; - vals[node] = *(reinterpret_cast(&result)); - } -} +PROCESS_GENERIC_BINARY_OP_FUNC(Mul, *) -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left & right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] & vals[inputs.at(node)[1].source]; - } - } - // No AND for floats. -} +PROCESS_GENERIC_BINARY_OP_FUNC(Div, /) -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left | right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] | vals[inputs.at(node)[1].source]; - } - } - // No OR for floats. -} +PROCESS_GENERIC_BINARY_OP_FUNC(Less, <) -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left ^ right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] ^ vals[inputs.at(node)[1].source]; - } - } - // No XOR for floats. -} +PROCESS_GENERIC_BINARY_OP_FUNC(LessEq, <=) -template <> -void DFCXXSimulator::processUnaryOp(RecordedValues &vals, - Node &node) { - vals[node] = ~(vals[inputs.at(node)[0].source]); -} +PROCESS_GENERIC_BINARY_OP_FUNC(Greater, >) -template <> -void DFCXXSimulator::processUnaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t result = -left; - vals[node] = *(reinterpret_cast(&result)); - } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double result = -left; - vals[node] = *(reinterpret_cast(&result)); - } -} +PROCESS_GENERIC_BINARY_OP_FUNC(GreaterEq, >=) -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left < right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] < vals[inputs.at(node)[1].source]; - } - } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - double result = left < right; - vals[node] = *(reinterpret_cast(&result)); - } -} +PROCESS_GENERIC_BINARY_OP_FUNC(Eq, ==) -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left <= right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] <= vals[inputs.at(node)[1].source]; - } - } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - double result = left <= right; - vals[node] = *(reinterpret_cast(&result)); - } -} +PROCESS_GENERIC_BINARY_OP_FUNC(Neq, !=) -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left > right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] > vals[inputs.at(node)[1].source]; - } - } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - double result = left > right; - vals[node] = *(reinterpret_cast(&result)); - } +#define PROCESS_GENERIC_BITWISE_BINARY_OP_FUNC(OP_NAME, OP) \ +static bool GENERIC_FUNC_NAME(OP_NAME)(RecordedValues &vals, \ + const Node &node, \ + const Inputs &inputs, \ + const IOVars &inData, \ + IOVars &outData, uint64_t ind) { \ + vals[node] = \ + vals[inputs.at(node)[0].source] OP vals[inputs.at(node)[1].source]; \ + return true; \ +} + +PROCESS_GENERIC_BITWISE_BINARY_OP_FUNC(And, &) + +PROCESS_GENERIC_BITWISE_BINARY_OP_FUNC(Or, |) + +PROCESS_GENERIC_BITWISE_BINARY_OP_FUNC(Xor, ^) + +static bool processNotOp(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind) { + vals[node] = ~(vals[inputs.at(node)[0].source]); + return true; } -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { +static bool processNegOp(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind) { DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - int64_t result = left >= right; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] >= vals[inputs.at(node)[1].source]; - } + int64_t left = + *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + int64_t result = -left; + vals[node] = + *(reinterpret_cast(&result)); + } else if (type->isFloat()) { + double left = + *(reinterpret_cast(&vals[inputs.at(node)[0].source])); + double result = -left; + vals[node] = + *(reinterpret_cast(&result)); } else { - double left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double right = *(reinterpret_cast(&vals[inputs.at(node)[1].source])); - double result = left >= right; - vals[node] = *(reinterpret_cast(&result)); + return false; } + return true; } -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - vals[node] = vals[inputs.at(node)[0].source] == vals[inputs.at(node)[1].source]; +static bool processShiftLeftOp(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind) { + vals[node] = vals[inputs.at(node)[0].source] << node.data.bitShift; + return true; } -template <> -void DFCXXSimulator::processBinaryOp(RecordedValues &vals, - Node &node) { - vals[node] = vals[inputs.at(node)[0].source] != vals[inputs.at(node)[1].source]; +static bool processShiftRightOp(RecordedValues &vals, const Node &node, + const Inputs &inputs, const IOVars &inData, + IOVars &outData, uint64_t ind) { + vals[node] = vals[inputs.at(node)[0].source] >> node.data.bitShift; + return true; } -void DFCXXSimulator::processShiftLeft(RecordedValues &vals, Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t result = left << node.data.bitShift; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] << node.data.bitShift; - } +bool DFCXXSimulator::processOp(RecordedValues &vals, const Node &node, + const IOVars &inData, IOVars &outData, + uint64_t ind) { + if (funcs.find(node.type) == funcs.end()) { + return false; } - // No left bit shift for floats. + return funcs.at(node.type)(vals, node, inputs, inData, outData, ind); } -void DFCXXSimulator::processShiftRight(RecordedValues &vals, Node &node) { - DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); - if (type->isFixed()) { - if (((FixedType*) type)->isSigned()) { - int64_t left = *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t result = left >> node.data.bitShift; - vals[node] = *(reinterpret_cast(&result)); - } else { - vals[node] = vals[inputs.at(node)[0].source] >> node.data.bitShift; - } - } - // No right bit shift for floats. +DFCXXSimulator::DFCXXSimulator(std::vector &nodes, + const Inputs &inputs) : + nodes(nodes), + inputs(inputs), + funcs({ + {OpType::IN, processInput}, + {OpType::OUT, processOutput}, + {OpType::CONST, processConst}, + {OpType::MUX, processMux}, + {OpType::ADD, GENERIC_FUNC_NAME(Add)}, + {OpType::SUB, GENERIC_FUNC_NAME(Sub)}, + {OpType::MUL, GENERIC_FUNC_NAME(Mul)}, + {OpType::DIV, GENERIC_FUNC_NAME(Div)}, + {OpType::AND, GENERIC_FUNC_NAME(And)}, + {OpType::OR, GENERIC_FUNC_NAME(Or)}, + {OpType::XOR, GENERIC_FUNC_NAME(Xor)}, + {OpType::NOT, processNotOp}, + {OpType::NEG, processNegOp}, + {OpType::LESS, GENERIC_FUNC_NAME(Less)}, + {OpType::LESSEQ, GENERIC_FUNC_NAME(LessEq)}, + {OpType::GREATER, GENERIC_FUNC_NAME(Greater)}, + { + OpType::GREATEREQ, + GENERIC_FUNC_NAME(GreaterEq)}, + {OpType::EQ, GENERIC_FUNC_NAME(Eq)}, + {OpType::NEQ, GENERIC_FUNC_NAME(Neq)}, + {OpType::SHL, processShiftLeftOp}, + {OpType::SHR, processShiftRightOp}}) { + // TODO: Add offset support in the future. } -bool DFCXXSimulator::runSim(IOVars &input, - IOVars &output, +bool DFCXXSimulator::runSim(IOVars &inData, + IOVars &outData, uint64_t count) { // Node->value mapping is initialized. This allows us // to rememeber the relevant value for the operand node. @@ -358,30 +238,8 @@ bool DFCXXSimulator::runSim(IOVars &input, RecordedValues vals; for (uint64_t i = 0; i < count; ++i) { for (Node &node : nodes) { - switch (node.type) { - case OFFSET: - return false; // TODO: Add offset support in the future. - case IN: processInput(vals, node, input, i); break; - case OUT: processOutput(vals, node, output, i); break; - case CONST: processConst(vals, node); break; - case MUX: processMux(vals, node); break; - case ADD: processBinaryOp(vals, node); break; - case SUB: processBinaryOp(vals, node); break; - case MUL: processBinaryOp(vals, node); break; - case DIV: processBinaryOp(vals, node); break; - case AND: processBinaryOp(vals, node); break; - case OR: processBinaryOp(vals, node); break; - case XOR: processBinaryOp(vals, node); break; - case NOT: processUnaryOp(vals, node); break; - case NEG: processUnaryOp(vals, node); break; - case LESS: processBinaryOp(vals, node); break; - case LESSEQ: processBinaryOp(vals, node); break; - case GREATER: processBinaryOp(vals, node); break; - case GREATEREQ: processBinaryOp(vals, node); break; - case EQ: processBinaryOp(vals, node); break; - case NEQ: processBinaryOp(vals, node); break; - case SHL: processShiftLeft(vals, node); break; - case SHR: processShiftRight(vals, node); break; + if (!processOp(vals, node, inData, outData, i)) { + return false; } } } @@ -389,10 +247,10 @@ bool DFCXXSimulator::runSim(IOVars &input, } bool DFCXXSimulator::writeOutput(std::ofstream &out, - IOVars &output, + const IOVars &outData, uint64_t count) { - auto outFunc = [&out, &output] (uint64_t iter) { - for (auto &kv : output) { + auto outFunc = [&out, &outData] (uint64_t iter) { + for (const auto &kv : outData) { out << kv.first << " 0x" << std::hex << kv.second[iter] << "\n"; } }; @@ -407,13 +265,13 @@ bool DFCXXSimulator::writeOutput(std::ofstream &out, bool DFCXXSimulator::simulate(std::ifstream &in, std::ofstream &out) { - IOVars input; - IOVars output; - while (uint64_t count = readInputData(in, input)) { + IOVars inData; + IOVars outData; + while (uint64_t count = readInput(in, inData)) { // If either the simulation itself or writing to output file // fails - return false. - if (!runSim(input, output, count) || - !writeOutput(out, output, count)) { + if (!runSim(inData, outData, count) || + !writeOutput(out, outData, count)) { return false; } } From 6c48c881dcd80d262e66fa1e015628c4553928b1 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Mon, 26 Aug 2024 19:09:47 +0300 Subject: [PATCH 15/21] DFCxx simulation now outputs VCD files. --- src/model/dfcxx/includeDev/dfcxx/simulator.h | 23 ++- src/model/dfcxx/lib/dfcxx/CMakeLists.txt | 1 + src/model/dfcxx/lib/dfcxx/simulator.cpp | 170 ++++++++++++++----- src/model/dfcxx/templates/vcd.tpl | 17 ++ 4 files changed, 163 insertions(+), 48 deletions(-) create mode 100644 src/model/dfcxx/templates/vcd.tpl diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index e1fde42..6cce544 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -19,6 +19,12 @@ #include #include +// This forward declaration is needed to avoid +// users having to include CTemplate headers. +namespace ctemplate { + class TemplateDictionary; +} + namespace dfcxx { typedef uint64_t SimValue; @@ -34,7 +40,7 @@ typedef std::unordered_map RecordedValues; typedef bool (*OpSimulationFunc)(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind); + uint64_t ind); typedef std::unordered_map OpSimulationFuncs; @@ -46,12 +52,21 @@ class DFCXXSimulator { private: uint64_t readInput(std::ifstream &in, IOVars &inData); - bool runSim(IOVars &inData, IOVars &outData, uint64_t count); + bool runSim(RecordedValues &vals, IOVars &inData, uint64_t iter); bool processOp(RecordedValues &vals, const Node &node, - const IOVars &inData, IOVars &outData, uint64_t ind); + const IOVars &inData, uint64_t ind); - bool writeOutput(std::ofstream &out, const IOVars &outData, uint64_t count); + void genHeader(ctemplate::TemplateDictionary *dict, + const RecordedValues &vals, + std::unordered_map &idMap, + uint64_t &counter); + + void writeOutput(ctemplate::TemplateDictionary *dict, + const RecordedValues &vals, + uint64_t startInd, + uint64_t iter, + const std::unordered_map &idMap); std::vector &nodes; const Inputs &inputs; diff --git a/src/model/dfcxx/lib/dfcxx/CMakeLists.txt b/src/model/dfcxx/lib/dfcxx/CMakeLists.txt index f99f761..2d75803 100644 --- a/src/model/dfcxx/lib/dfcxx/CMakeLists.txt +++ b/src/model/dfcxx/lib/dfcxx/CMakeLists.txt @@ -47,6 +47,7 @@ set(TEMPLATES_PATH "${PROJECT_SOURCE_DIR}/templates") add_compile_definitions( TEMPLATES_PATH="${TEMPLATES_PATH}" DOT_TEMPLATE_PATH="${TEMPLATES_PATH}/dot.tpl" + VCD_TEMPLATE_PATH="${TEMPLATES_PATH}/vcd.tpl" ) ## MLIRDFCIR is ensured to be compiled beforehand. diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index d319231..07fa3c1 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -10,6 +10,10 @@ #include "dfcxx/types/types.h" #include "dfcxx/vars/vars.h" +#include "ctemplate/template.h" + +#include +#include #include namespace dfcxx { @@ -41,7 +45,7 @@ uint64_t DFCXXSimulator::readInput(std::ifstream &in, static bool processInput(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind) { + uint64_t ind) { auto name = std::string(DFVariable(node.var).getName()); vals[node] = inData.at(name)[ind]; return true; @@ -49,24 +53,23 @@ static bool processInput(RecordedValues &vals, const Node &node, static bool processOutput(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind) { + uint64_t ind) { auto name = std::string(DFVariable(node.var).getName()); // Take output's only connection and assign the existing source value. vals[node] = vals[inputs.at(node)[0].source]; - outData[name][ind] = vals[node]; return true; } static bool processConst(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind) { + uint64_t ind) { vals[node] = ((DFConstant *) node.var)->getUInt(); return true; } static bool processMux(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind) { + uint64_t ind) { auto muxedValue = vals[inputs.at(node)[node.data.muxId].source]; vals[node] = vals[inputs.at(node)[muxedValue + 1].source]; return true; @@ -78,7 +81,6 @@ static bool GENERIC_FUNC_NAME(OP_NAME)(RecordedValues &vals, \ const Node &node, \ const Inputs &inputs, \ const IOVars &inData, \ - IOVars &outData, \ uint64_t ind) { \ DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); \ if (type->isFixed()) { \ @@ -133,7 +135,7 @@ static bool GENERIC_FUNC_NAME(OP_NAME)(RecordedValues &vals, \ const Node &node, \ const Inputs &inputs, \ const IOVars &inData, \ - IOVars &outData, uint64_t ind) { \ + uint64_t ind) { \ vals[node] = \ vals[inputs.at(node)[0].source] OP vals[inputs.at(node)[1].source]; \ return true; \ @@ -147,14 +149,14 @@ PROCESS_GENERIC_BITWISE_BINARY_OP_FUNC(Xor, ^) static bool processNotOp(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind) { + uint64_t ind) { vals[node] = ~(vals[inputs.at(node)[0].source]); return true; } static bool processNegOp(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind) { + uint64_t ind) { DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { int64_t left = @@ -176,25 +178,24 @@ static bool processNegOp(RecordedValues &vals, const Node &node, static bool processShiftLeftOp(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind) { + uint64_t ind) { vals[node] = vals[inputs.at(node)[0].source] << node.data.bitShift; return true; } static bool processShiftRightOp(RecordedValues &vals, const Node &node, const Inputs &inputs, const IOVars &inData, - IOVars &outData, uint64_t ind) { + uint64_t ind) { vals[node] = vals[inputs.at(node)[0].source] >> node.data.bitShift; return true; } bool DFCXXSimulator::processOp(RecordedValues &vals, const Node &node, - const IOVars &inData, IOVars &outData, - uint64_t ind) { + const IOVars &inData, uint64_t ind) { if (funcs.find(node.type) == funcs.end()) { return false; } - return funcs.at(node.type)(vals, node, inputs, inData, outData, ind); + return funcs.at(node.type)(vals, node, inputs, inData, ind); } DFCXXSimulator::DFCXXSimulator(std::vector &nodes, @@ -228,53 +229,134 @@ DFCXXSimulator::DFCXXSimulator(std::vector &nodes, // TODO: Add offset support in the future. } -bool DFCXXSimulator::runSim(IOVars &inData, - IOVars &outData, - uint64_t count) { - // Node->value mapping is initialized. This allows us +bool DFCXXSimulator::runSim(RecordedValues &vals, + IOVars &inData, + uint64_t iter) { + // Node->value mapping is updated. This allows us // to rememeber the relevant value for the operand node. - // With every single "clock" (loop iteration) input - // nodes' mapping is updated with the value from the buffer. - RecordedValues vals; - for (uint64_t i = 0; i < count; ++i) { - for (Node &node : nodes) { - if (!processOp(vals, node, inData, outData, i)) { - return false; - } + // With every single "clock" input nodes' mapping is updated + // with the value from the buffer. + for (Node &node : nodes) { + if (!processOp(vals, node, inData, iter)) { + return false; } } return true; } -bool DFCXXSimulator::writeOutput(std::ofstream &out, - const IOVars &outData, - uint64_t count) { - auto outFunc = [&out, &outData] (uint64_t iter) { - for (const auto &kv : outData) { - out << kv.first << " 0x" << std::hex << kv.second[iter] << "\n"; +static inline std::string valueToBinary(SimValue value, uint64_t width) { + std::stringstream stream; + uint64_t lastBitId = width - 1; + // Every iteration we take leftmost bit and convert it to a char. + for (uint64_t bitId = 0; bitId < width; ++bitId) { + stream << char(((value >> (lastBitId - bitId)) & 1) + 48); + } + return stream.str(); +} + +void DFCXXSimulator::writeOutput(ctemplate::TemplateDictionary *dict, + const RecordedValues &vals, + uint64_t startInd, + uint64_t iter, + const std::unordered_map &idMap) { + ctemplate::TemplateDictionary *tick = + dict->AddSectionDictionary("TICKS"); + tick->SetValue("TICK", std::to_string(startInd + iter)); + for (const auto &kv : vals) { + ctemplate::TemplateDictionary *value = + tick->AddSectionDictionary("VALUES"); + value->SetValue("VALUE", + valueToBinary(kv.second, + kv.first.var->getType()->getTotalBits())); + value->SetValue("NAME", idMap.at(kv.first)); + } +} + +void DFCXXSimulator::genHeader(ctemplate::TemplateDictionary *dict, + const RecordedValues &vals, + std::unordered_map &idMap, + uint64_t &counter) { + auto time = std::time(nullptr); + auto *localTime = std::localtime(&time); + dict->SetFormattedValue("GEN_TIME", + "%d-%d-%d %d:%d:%d", + localTime->tm_mday, + localTime->tm_mon + 1, + localTime->tm_year + 1900, + localTime->tm_hour, + localTime->tm_min, + localTime->tm_sec); + + auto getName = [&idMap, &counter] (const Node &node) -> std::string { + // If the node is named - just save and return the name. + auto name = DFVariable(node.var).getName(); + if (!name.empty()) { + return (idMap[node] = name.data()); } + // If the mapping contains the node name - return it. + auto it = idMap.find(node); + if (it != idMap.end()) { + return it->second; + } + // Otherwise create and return the new node name mapping. + return (idMap[node] = "node" + std::to_string(counter++)); }; - - outFunc(0); - for (uint64_t i = 1; i < count; ++i) { - out << "\n"; - outFunc(i); + + for (const auto &kv : vals) { + std::string name = getName(kv.first); + auto width = kv.first.var->getType()->getTotalBits(); + + ctemplate::TemplateDictionary *var = + dict->AddSectionDictionary("VARS"); + var->SetValue("WIDTH", + std::to_string(width)); + var->SetValue("NAME", name); + + ctemplate::TemplateDictionary *initVar = + dict->AddSectionDictionary("INIT_VARS"); + initVar->SetValue("INIT_VALUE", std::string(width, 'x')); + initVar->SetValue("NAME", name); } - return true; } bool DFCXXSimulator::simulate(std::ifstream &in, std::ofstream &out) { IOVars inData; - IOVars outData; + RecordedValues vals; + bool headerGenerated = false; + uint64_t startInd = 1; + uint64_t counter = 0; + std::unordered_map idMapping; + ctemplate::TemplateDictionary *dict = + new ctemplate::TemplateDictionary("vcd"); + while (uint64_t count = readInput(in, inData)) { - // If either the simulation itself or writing to output file - // fails - return false. - if (!runSim(inData, outData, count) || - !writeOutput(out, outData, count)) { - return false; + for (uint64_t iter = 0; iter < count; ++iter) { + // If the simulation fails - return false. + if (!runSim(vals, inData, iter)) { + delete dict; + return false; + } + // If it's the first iteration - generate .vcd headers. + if (!headerGenerated) { + genHeader(dict, vals, idMapping, counter); + headerGenerated = true; + } + writeOutput(dict, vals, startInd, iter, idMapping); } + startInd += count; } + dict->SetValue("FINAL_TICK", std::to_string(startInd)); + std::string result; + ctemplate::ExpandTemplate(VCD_TEMPLATE_PATH, + ctemplate::DO_NOT_STRIP, + dict, + &result); + + out << result; + + delete dict; return true; } diff --git a/src/model/dfcxx/templates/vcd.tpl b/src/model/dfcxx/templates/vcd.tpl new file mode 100644 index 0000000..9fe8f3d --- /dev/null +++ b/src/model/dfcxx/templates/vcd.tpl @@ -0,0 +1,17 @@ +$date {{GEN_TIME}} $end +$version Utopia HLS $end +$timescale 1ps $end + +$scope module logic $end +{{#VARS}}$var wire {{WIDTH}} {{NAME}} {{NAME}} $end +{{/VARS}}$upscope $end +$enddefinitions $end + +$dumpvars +{{#INIT_VARS}}b{{INIT_VALUE}} {{NAME}} +{{/INIT_VARS}}$end + +{{#TICKS}}#{{TICK}} +{{#VALUES}}b{{VALUE}} {{NAME}} +{{/VALUES}} +{{/TICKS}}#{{FINAL_TICK}} From 031d2d782ef439d5f3208cd2f14d034dd468b161 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Mon, 26 Aug 2024 20:11:43 +0300 Subject: [PATCH 16/21] README.md was updated. --- README.md | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6913873..7d0006e 100644 --- a/README.md +++ b/README.md @@ -211,9 +211,9 @@ The compiled Utopia HLS executable has a CLI to accept a number of parameters af For the executable there are three general arguments: `-h,--help`, `-H,--help-all` and `-v,--version` for printing simple and extended help-messages, and printing current executable's version respectively. -Unless neither of the three arguments is used, first argument is the mode which the executable has to function in. Currently there is only one available mode `hls`. +Unless neither of the three arguments is used, first argument is the mode which the executable has to function in. Currently there are only two available modes: `hls` and `sim`. -The list of arguments for `hls`-mode is presented below: +`hls` mode is used to translate the provided DFCxx kernel to different output formats. The list of arguments for `hls`-mode is presented below: * `-h,--help`: *optional* flag; used to print the help-message about other arguments. * `--config `: *required* filesystem-path option; used to specify the file for a JSON latency configuration file. Its format is presented in *JSON Configuration* section. @@ -232,6 +232,12 @@ Here is an example of an Utopia HLS CLI call: umain hls --config ~/utopia-user/config.json --out-sv ~/outFile.sv --out-dfcir ~/outFile2.mlir -a ``` +`sim` mode is used to simulate the provided DFCxx kernel. The list of arguments for `sim`-mode is presented below: + +* `-h,--help`: *optional* flag; used to print the help-message about other arguments. +* `--in `: *optional* filesystem-path option; used to specify the input file for simulation data (default: `sim.txt`). Its format is presented in *DFCxx Simulation Input Format* section. +* `--out `: *optional* filesystem-path option; used to specify the output VCD file (default: `sim_out.txt`). + ### JSON Configuration Latency configuration for each computational operation (number of pipeline stages) used in a DFCxx kernel is provided via a JSON file. @@ -268,6 +274,33 @@ Here is an example of a JSON configuration file, containing latencies for multip } ``` +### DFCxx Simulation Input Format + +DFCxx kernels can be simulated to check that they describe computations as expected. The simulation doesn't include scheduling-related characteristics, thus DFCxx concepts like *offsets* are not supported, every computational node has to use **and** accept some value. +The format to provide simulation input data is the following: + +* input data is divided into blocks separated with a newline character (`\n`) - one block for each clock period +* every block has a number of lines, each of which has the name of some **input** stream/scalar value and its hex-value (these values do not have a type - it is assumed from the corresponding computational nodes) +* stream/scalar value name and the value are separated with a single space character (` `) +* the provided value must be a valid hex-value: with or without `0x`, with either lower- or uppercase letters +* if some stream/scalar value is present twice or more in the same block - its latest described value is used +* after the last block **no newline character can be present** + +Here is an example of an input simulation file for `MuxMul` kernel, which has two input streams `x` and `ctrl`. + +```txt +x 0x32 +ctrl 0x1 + +x 0x45 +ctrl 0x0 + +x 0x56 +ctrl 0x1 +``` + +In this example, `x` accepts values `50` (`0x32`), `69` (`0x45`) and `86` (`0x56`), while `ctrl` accepts `1`, `0` and `1`. This means that 3 clock periods will be simulated for the provided kernel. + ## Examples Root subdirectory `examples` contains different examples of DFCxx kernels, `start`-function definitions and JSON configuration files. @@ -282,7 +315,15 @@ build/src/umain hls --config examples/polynomial2/add_int_2_mul_int3.json -a --o The execution command is going to pass a JSON configuration file (with 2 and 3 pipeline stages for integer addition and multiplication respectively) to Utopia HLS, resulting in the creation of the file `output`, containing a SystemVerilog -module for Polynomial2 kernel with a greedy ASAP-scheduling. +module for `Polynomial2` kernel with a greedy ASAP-scheduling. + +The same kernel can be simulated with: + +```bash +build/src/umain sim --in examples/polynomial2/sim.txt --out output.vcd +``` + +This command uses the simulation data from `sim.txt` file to output a VCD-file `output.vcd`. ## DFCxx Documentation From 252e0c475032ec456830c5df76da4a511c1e6d13 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Tue, 27 Aug 2024 18:15:41 +0300 Subject: [PATCH 17/21] Fixes regarding Pull Request review. --- README.md | 2 +- config.json | 2 +- src/main.cpp | 2 +- src/model/dfcxx/include/dfcxx/graph.h | 4 +- src/model/dfcxx/include/dfcxx/kernel.h | 2 +- .../dfcxx/include/dfcxx/varbuilders/builder.h | 2 +- src/model/dfcxx/include/dfcxx/vars/var.h | 2 +- .../includeDev/dfcxx/IRbuilders/builder.h | 1 - src/model/dfcxx/includeDev/dfcxx/simulator.h | 4 +- .../dfcxx/lib/dfcxx/IRbuilders/builder.cpp | 149 +++--- src/model/dfcxx/lib/dfcxx/constant.cpp | 12 +- src/model/dfcxx/lib/dfcxx/control.cpp | 2 +- src/model/dfcxx/lib/dfcxx/graph.cpp | 4 +- src/model/dfcxx/lib/dfcxx/io.cpp | 8 +- src/model/dfcxx/lib/dfcxx/kernel.cpp | 2 +- src/model/dfcxx/lib/dfcxx/simulator.cpp | 67 +-- src/model/dfcxx/lib/dfcxx/vars/constant.cpp | 492 ++++-------------- src/model/dfcxx/lib/dfcxx/vars/scalar.cpp | 155 ++---- src/model/dfcxx/lib/dfcxx/vars/stream.cpp | 155 ++---- src/options.h | 17 +- 20 files changed, 326 insertions(+), 758 deletions(-) diff --git a/README.md b/README.md index 7d0006e..0e9948c 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ umain hls --config ~/utopia-user/config.json --out-sv ~/outFile.sv --out-dfcir ~ * `-h,--help`: *optional* flag; used to print the help-message about other arguments. * `--in `: *optional* filesystem-path option; used to specify the input file for simulation data (default: `sim.txt`). Its format is presented in *DFCxx Simulation Input Format* section. -* `--out `: *optional* filesystem-path option; used to specify the output VCD file (default: `sim_out.txt`). +* `--out `: *optional* filesystem-path option; used to specify the output VCD file (default: `sim_out.vcd`). ### JSON Configuration diff --git a/config.json b/config.json index 9004b22..2ac439d 100644 --- a/config.json +++ b/config.json @@ -11,6 +11,6 @@ }, "sim": { "in" : "sim.txt", - "out" : "sim_out.txt" + "out" : "sim_out.vcd" } } diff --git a/src/main.cpp b/src/main.cpp index 87948dd..79cf2eb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,7 +45,7 @@ struct SimContext { int hlsMain(const HlsContext &context) { auto kernel = start(); bool useASAP = context.options.asapScheduler; - return !kernel->compile(context.options.latConfig, + return !kernel->compile(context.options.latencyCfg, context.options.outNames, (useASAP) ? dfcxx::Scheduler::ASAP : dfcxx::Scheduler::Linear); diff --git a/src/model/dfcxx/include/dfcxx/graph.h b/src/model/dfcxx/include/dfcxx/graph.h index 0aaa5fd..c41ffa1 100644 --- a/src/model/dfcxx/include/dfcxx/graph.h +++ b/src/model/dfcxx/include/dfcxx/graph.h @@ -28,9 +28,9 @@ class Graph { std::unordered_map connections; public: - const std::unordered_set& getNodes() const; + const std::unordered_set &getNodes() const; - const std::unordered_set& getStartNodes() const; + const std::unordered_set &getStartNodes() const; const std::unordered_map> &getInputs() const; diff --git a/src/model/dfcxx/include/dfcxx/kernel.h b/src/model/dfcxx/include/dfcxx/kernel.h index f2ea8da..a64fe11 100644 --- a/src/model/dfcxx/include/dfcxx/kernel.h +++ b/src/model/dfcxx/include/dfcxx/kernel.h @@ -58,7 +58,7 @@ class Kernel { virtual std::string_view getName() = 0; - const Graph& getGraph() const; + const Graph &getGraph() const; bool compile(const DFLatencyConfig &config, const std::vector &outputPaths, diff --git a/src/model/dfcxx/include/dfcxx/varbuilders/builder.h b/src/model/dfcxx/include/dfcxx/varbuilders/builder.h index db3e0b8..eb9c1c7 100644 --- a/src/model/dfcxx/include/dfcxx/varbuilders/builder.h +++ b/src/model/dfcxx/include/dfcxx/varbuilders/builder.h @@ -13,7 +13,7 @@ namespace dfcxx { -struct KernMeta; // Forward declaration to omit circicular dependency. +struct KernMeta; // Forward declaration to omit cyclic dependency. class VarBuilder { public: diff --git a/src/model/dfcxx/include/dfcxx/vars/var.h b/src/model/dfcxx/include/dfcxx/vars/var.h index da1d246..0bbffd3 100644 --- a/src/model/dfcxx/include/dfcxx/vars/var.h +++ b/src/model/dfcxx/include/dfcxx/vars/var.h @@ -17,7 +17,7 @@ namespace dfcxx { class VarBuilder; -struct KernMeta; // Forward declaration to omit circicular dependency. +struct KernMeta; // Forward declaration to omit cyclic dependency. class DFVariableImpl { friend VarBuilder; diff --git a/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h b/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h index f449206..6ab2dd7 100644 --- a/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h +++ b/src/model/dfcxx/includeDev/dfcxx/IRbuilders/builder.h @@ -24,7 +24,6 @@ class DFCIRBuilder { mlir::MLIRContext ctx; mlir::OwningOpRef module; DFCIRTypeConverter conv; - //std::unordered_map> muxMap; void translate(Node node, const Graph &graph, mlir::OpBuilder &builder, std::unordered_map &map); diff --git a/src/model/dfcxx/includeDev/dfcxx/simulator.h b/src/model/dfcxx/includeDev/dfcxx/simulator.h index 6cce544..7b8d55a 100644 --- a/src/model/dfcxx/includeDev/dfcxx/simulator.h +++ b/src/model/dfcxx/includeDev/dfcxx/simulator.h @@ -30,9 +30,9 @@ namespace dfcxx { typedef uint64_t SimValue; // Buffer size for reading from and writing to simulation data files. -#define BUF_SIZE 200 +#define SIM_DATA_BUF_SIZE 200 -typedef std::map> IOVars; +typedef std::map> IOVars; typedef std::unordered_map> Inputs; diff --git a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp index 1f35c79..dd2ebe8 100644 --- a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp @@ -47,6 +47,8 @@ mlir::ModuleOp DFCIRBuilder::buildModule(Kernel *kern) { return module.get(); } +#define MLIR_INT_ATTR_WIDTH 64 + void DFCIRBuilder::translate(Node node, const Graph &graph, mlir::OpBuilder &builder, std::unordered_map &map) { @@ -56,42 +58,40 @@ void DFCIRBuilder::translate(Node node, const Graph &graph, auto nameAttr = mlir::StringAttr::get(&ctx, node.var->getName()); + mlir::Operation *newOp = nullptr; + switch (node.type) { case OFFSET: { Node in = ins[0].source; - auto type = mlir::IntegerType::get(builder.getContext(), 64, + auto type = mlir::IntegerType::get(builder.getContext(), + MLIR_INT_ATTR_WIDTH, mlir::IntegerType::Signless); auto attr = mlir::IntegerAttr::get(type, node.data.offset); - auto newOp = builder.create(loc, conv[in.var], - map[in], attr); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[in.var], + map[in], attr); break; } case IN: { if (node.var->isStream()) { - auto newOp = builder.create(loc, conv[node.var], - nameAttr, nullptr); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + nameAttr, nullptr); } else { - auto newOp = builder.create(loc, - conv[node.var], - nameAttr); - map[node] = newOp.getResult(); + newOp = builder.create(loc, + conv[node.var], + nameAttr); } break; } case OUT: { if (node.var->isStream()) { - auto newOp = builder.create(loc, conv[node.var], - nameAttr, nullptr, - nullptr); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + nameAttr, nullptr, + nullptr); } else { - auto newOp = builder.create(loc, - conv[node.var], - nameAttr, - nullptr); - map[node] = newOp.getResult(); + newOp = builder.create(loc, + conv[node.var], + nameAttr, + nullptr); } break; } @@ -122,9 +122,8 @@ void DFCIRBuilder::translate(Node node, const Graph &graph, } } auto attr = mlir::IntegerAttr::get(attrType, val); - auto newOp = builder.create(loc, conv[node.var], - attr); - map[node] = newOp.getRes(); + newOp = builder.create(loc, conv[node.var], + attr); break; } case MUX: { @@ -140,132 +139,116 @@ void DFCIRBuilder::translate(Node node, const Graph &graph, } } - auto newOp = builder.create(loc, conv[node.var], - map[ctrl], mux); - map[node] = newOp.getRes(); + newOp = builder.create(loc, conv[node.var], + map[ctrl], mux); break; } case ADD: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], map[second]); break; } case SUB: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], map[second]); break; } case MUL: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], map[second]); break; } case DIV: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], map[second]); break; } case AND: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], map[second]); break; } case OR: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], map[second]); break; } case XOR: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], map[second]); break; } case NOT: { Node first = ins[0].source; - auto newOp = builder.create(loc, conv[node.var], - map[first]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first]); break; } case NEG: { Node first = ins[0].source; - auto newOp = builder.create(loc, conv[node.var], - map[first]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first]); break; } case LESS: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], map[second]); break; } case LESSEQ: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); break; } case GREATER: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); break; } case GREATEREQ: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); break; } case EQ: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); break; } case NEQ: { Node first = ins[0].source; Node second = ins[1].source; - auto newOp = builder.create(loc, conv[node.var], - map[first], - map[second]); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], + map[second]); break; } case SHL: { @@ -274,9 +257,8 @@ void DFCIRBuilder::translate(Node node, const Graph &graph, mlir::IntegerType::Signless); auto attr = mlir::IntegerAttr::get(attrType, node.data.bitShift); - auto newOp = builder.create(loc, conv[node.var], - map[first], attr); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], attr); break; } case SHR: { @@ -285,12 +267,15 @@ void DFCIRBuilder::translate(Node node, const Graph &graph, mlir::IntegerType::Signless); auto attr = mlir::IntegerAttr::get(attrType, node.data.bitShift); - auto newOp = builder.create(loc, conv[node.var], - map[first], attr); - map[node] = newOp.getResult(); + newOp = builder.create(loc, conv[node.var], + map[first], attr); break; } + default: assert(false); } + + map[node] = newOp->getResult(0); + auto &connections = graph.getConnections(); if (connections.find(node) != connections.end()) { auto conSrc = connections.at(node).source; diff --git a/src/model/dfcxx/lib/dfcxx/constant.cpp b/src/model/dfcxx/lib/dfcxx/constant.cpp index 0d57d2a..bcf91b4 100644 --- a/src/model/dfcxx/lib/dfcxx/constant.cpp +++ b/src/model/dfcxx/lib/dfcxx/constant.cpp @@ -14,31 +14,31 @@ Constant::Constant(KernMeta &meta) : meta(meta) {} DFVariable Constant::var(const DFType &type, int64_t value) { auto *var = meta.varBuilder.buildConstant(meta, type, - DFConstant::Value{ + DFConstant::Value { .int_ = value }); meta.storage.addVariable(var); - meta.graph.addNode(var, OpType::CONST, NodeData{}); + meta.graph.addNode(var, OpType::CONST, NodeData {}); return var; } DFVariable Constant::var(const DFType &type, uint64_t value) { auto *var = meta.varBuilder.buildConstant(meta, type, - DFConstant::Value{ + DFConstant::Value { .uint_ = value }); meta.storage.addVariable(var); - meta.graph.addNode(var, OpType::CONST, NodeData{}); + meta.graph.addNode(var, OpType::CONST, NodeData {}); return var; } DFVariable Constant::var(const DFType &type, double value) { auto *var = meta.varBuilder.buildConstant(meta, type, - DFConstant::Value{ + DFConstant::Value { .double_ = value }); meta.storage.addVariable(var); - meta.graph.addNode(var, OpType::CONST, NodeData{}); + meta.graph.addNode(var, OpType::CONST, NodeData {}); return var; } diff --git a/src/model/dfcxx/lib/dfcxx/control.cpp b/src/model/dfcxx/lib/dfcxx/control.cpp index d146248..364891d 100644 --- a/src/model/dfcxx/lib/dfcxx/control.cpp +++ b/src/model/dfcxx/lib/dfcxx/control.cpp @@ -19,7 +19,7 @@ DFVariable Control::mux(DFVariable ctrl, unsigned argsCount = args.size(); auto *var = meta.varBuilder.buildClone(argsData[0]); meta.storage.addVariable(var); - meta.graph.addNode(var, OpType::MUX, NodeData{.muxId = 0}); + meta.graph.addNode(var, OpType::MUX, NodeData {.muxId = 0}); meta.graph.addChannel(ctrl, var, 0, false); for (unsigned i = 0; i < argsCount; ++i) { meta.graph.addChannel(argsData[i], var, i + 1, false); diff --git a/src/model/dfcxx/lib/dfcxx/graph.cpp b/src/model/dfcxx/lib/dfcxx/graph.cpp index 1d453bb..44d4c4f 100644 --- a/src/model/dfcxx/lib/dfcxx/graph.cpp +++ b/src/model/dfcxx/lib/dfcxx/graph.cpp @@ -12,11 +12,11 @@ namespace dfcxx { -const std::unordered_set& Graph::getNodes() const { +const std::unordered_set &Graph::getNodes() const { return nodes; } -const std::unordered_set& Graph::getStartNodes() const { +const std::unordered_set &Graph::getStartNodes() const { return startNodes; } diff --git a/src/model/dfcxx/lib/dfcxx/io.cpp b/src/model/dfcxx/lib/dfcxx/io.cpp index 5281b3e..1be9b88 100644 --- a/src/model/dfcxx/lib/dfcxx/io.cpp +++ b/src/model/dfcxx/lib/dfcxx/io.cpp @@ -20,7 +20,7 @@ DFVariable IO::input(const std::string &name, const DFType &type) { meta, type); meta.storage.addVariable(var); - meta.graph.addNode(var, OpType::IN, NodeData{}); + meta.graph.addNode(var, OpType::IN, NodeData {}); return var; } @@ -30,7 +30,7 @@ DFVariable IO::inputScalar(const std::string &name, const DFType &type) { meta, type); meta.storage.addVariable(var); - meta.graph.addNode(var, OpType::IN, NodeData{}); + meta.graph.addNode(var, OpType::IN, NodeData {}); return var; } @@ -40,7 +40,7 @@ DFVariable IO::output(const std::string &name, const DFType &type) { meta, type); meta.storage.addVariable(var); - meta.graph.addNode(var, OpType::OUT, NodeData{}); + meta.graph.addNode(var, OpType::OUT, NodeData {}); return var; } @@ -50,7 +50,7 @@ DFVariable IO::outputScalar(const std::string &name, const DFType &type) { meta, type); meta.storage.addVariable(var); - meta.graph.addNode(var, OpType::OUT, NodeData{}); + meta.graph.addNode(var, OpType::OUT, NodeData {}); return var; } diff --git a/src/model/dfcxx/lib/dfcxx/kernel.cpp b/src/model/dfcxx/lib/dfcxx/kernel.cpp index fcbe08b..3cb639c 100644 --- a/src/model/dfcxx/lib/dfcxx/kernel.cpp +++ b/src/model/dfcxx/lib/dfcxx/kernel.cpp @@ -51,7 +51,7 @@ DFType Kernel::dfBool() { return meta.storage.addType(type); } -const Graph& Kernel::getGraph() const { +const Graph &Kernel::getGraph() const { return meta.graph; } diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index 07fa3c1..ed98f60 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -18,12 +18,14 @@ namespace dfcxx { +#define HEX_BASE 16 + uint64_t DFCXXSimulator::readInput(std::ifstream &in, IOVars &inData) { uint64_t ind = 0; std::string line; bool atLeastOne = false; - while (std::getline(in, line) && ind < BUF_SIZE) { + while (std::getline(in, line) && ind < SIM_DATA_BUF_SIZE) { // An empty line is treated as a data block delimiter. if (line.empty()) { ++ind; @@ -37,7 +39,7 @@ uint64_t DFCXXSimulator::readInput(std::ifstream &in, } atLeastOne = true; inData[line.substr(0, spaceInd)][ind] = - std::stoul(line.substr(spaceInd + 1), 0, 16); + std::stoul(line.substr(spaceInd + 1), 0, HEX_BASE); } // It is assumed that at least one data block exists. return atLeastOne ? (ind + 1) : 0; @@ -75,7 +77,27 @@ static bool processMux(RecordedValues &vals, const Node &node, return true; } +// Generic name for a simulation function. #define GENERIC_FUNC_NAME(OP_NAME) process##OP_NAME##Name + +// Casts the provided value to a concrete type in a system-dependent way. +#define CAST_SIM_VALUE_TO(TYPE, VALUE) *(reinterpret_cast(&VALUE)) + +// Generic procedure to perform the simulation +// for the concrete binary op and type of its operands. +#define GENERIC_BINARY_OP_SIM_WITH_TYPE(TYPE, VALS, INPUTS, NODE, OP) \ +TYPE left = CAST_SIM_VALUE_TO(TYPE, VALS[INPUTS.at(NODE)[0].source]); \ +TYPE right = CAST_SIM_VALUE_TO(TYPE, VALS[INPUTS.at(NODE)[1].source]); \ +TYPE result = left OP right; \ +VALS[NODE] = CAST_SIM_VALUE_TO(SimValue, result); + +// Generic procedure to perform the simulation +// for the concrete unary op and type of its operand. +#define GENERIC_UNARY_OP_SIM_WITH_TYPE(TYPE, VALS, INPUTS, NODE, OP) \ +TYPE left = CAST_SIM_VALUE_TO(TYPE, VALS[INPUTS.at(NODE)[0].source]); \ +TYPE result = OP left; \ +VALS[NODE] = CAST_SIM_VALUE_TO(SimValue, result); + #define PROCESS_GENERIC_BINARY_OP_FUNC(OP_NAME, OP) \ static bool GENERIC_FUNC_NAME(OP_NAME)(RecordedValues &vals, \ const Node &node, \ @@ -85,25 +107,12 @@ static bool GENERIC_FUNC_NAME(OP_NAME)(RecordedValues &vals, \ DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); \ if (type->isFixed()) { \ if (((FixedType*) type)->isSigned()) { \ - int64_t left = \ - *(reinterpret_cast(&vals[inputs.at(node)[0].source])); \ - int64_t right = \ - *(reinterpret_cast(&vals[inputs.at(node)[1].source])); \ - int64_t result = left OP right; \ - vals[node] = \ - *(reinterpret_cast(&result)); \ + GENERIC_BINARY_OP_SIM_WITH_TYPE(int64_t, vals, inputs, node, OP) \ } else { \ - vals[node] = \ - vals[inputs.at(node)[0].source] OP vals[inputs.at(node)[1].source]; \ + GENERIC_BINARY_OP_SIM_WITH_TYPE(uint64_t, vals, inputs, node, OP) \ } \ } else if (type->isFloat()) { \ - double left = \ - *(reinterpret_cast(&vals[inputs.at(node)[0].source])); \ - double right = \ - *(reinterpret_cast(&vals[inputs.at(node)[1].source])); \ - double result = left OP right; \ - vals[node] = \ - *(reinterpret_cast(&result)); \ + GENERIC_BINARY_OP_SIM_WITH_TYPE(double, vals, inputs, node, OP) \ } else { \ return false; \ } \ @@ -159,17 +168,13 @@ static bool processNegOp(RecordedValues &vals, const Node &node, uint64_t ind) { DFTypeImpl *type = (DFVariable(node.var).getType()).getImpl(); if (type->isFixed()) { - int64_t left = - *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - int64_t result = -left; - vals[node] = - *(reinterpret_cast(&result)); + if (((FixedType*) type)->isSigned()) { + GENERIC_UNARY_OP_SIM_WITH_TYPE(int64_t, vals, inputs, node, -) + } else { + GENERIC_UNARY_OP_SIM_WITH_TYPE(uint64_t, vals, inputs, node, -) + } } else if (type->isFloat()) { - double left = - *(reinterpret_cast(&vals[inputs.at(node)[0].source])); - double result = -left; - vals[node] = - *(reinterpret_cast(&result)); + GENERIC_UNARY_OP_SIM_WITH_TYPE(double, vals, inputs, node, -) } else { return false; } @@ -233,7 +238,7 @@ bool DFCXXSimulator::runSim(RecordedValues &vals, IOVars &inData, uint64_t iter) { // Node->value mapping is updated. This allows us - // to rememeber the relevant value for the operand node. + // to remember the relevant value for the operand node. // With every single "clock" input nodes' mapping is updated // with the value from the buffer. for (Node &node : nodes) { @@ -244,12 +249,14 @@ bool DFCXXSimulator::runSim(RecordedValues &vals, return true; } +#define ASCII_ZERO_CHAR_NUM 48 + static inline std::string valueToBinary(SimValue value, uint64_t width) { std::stringstream stream; uint64_t lastBitId = width - 1; // Every iteration we take leftmost bit and convert it to a char. for (uint64_t bitId = 0; bitId < width; ++bitId) { - stream << char(((value >> (lastBitId - bitId)) & 1) + 48); + stream << char(((value >> (lastBitId - bitId)) & 1) + ASCII_ZERO_CHAR_NUM); } return stream.str(); } diff --git a/src/model/dfcxx/lib/dfcxx/vars/constant.cpp b/src/model/dfcxx/lib/dfcxx/vars/constant.cpp index c07a81d..239756e 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/constant.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/constant.cpp @@ -33,223 +33,93 @@ DFTypeImpl *DFConstant::getType() { return &type; } +#define GENERIC_CONST_BINARY_OP(OP_TYPE, OP, VAR, RHS) \ +DFVariableImpl *VAR; \ +if (RHS.isConstant()) { \ + Value val {}; \ + DFConstant &casted = (DFConstant &) (RHS); \ + switch (kind) { \ + case INT: \ + val.int_ = value.int_ OP casted.value.int_; \ + break; \ + case UINT: \ + val.uint_ = value.uint_ OP casted.value.uint_; \ + break; \ + case FLOAT: \ + val.double_ = value.double_ OP casted.value.double_; \ + break; \ + } \ + VAR = meta.varBuilder.buildConstant(meta, &type, val); \ + meta.storage.addVariable(VAR); \ + meta.graph.addNode(VAR, OpType::CONST, NodeData {}); \ + return VAR; \ +} \ +VAR = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); \ +meta.storage.addVariable(VAR); \ +meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ +meta.graph.addChannel(this, VAR, 0, false); \ +meta.graph.addChannel(&RHS, VAR, 1, false); \ +return VAR; + DFVariableImpl *DFConstant::operator+(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.int_ = value.int_ + casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ + casted.value.uint_; - break; - case FLOAT: - val.double_ = value.double_ + casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, &type, val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::ADD, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_BINARY_OP(OpType::ADD, +, newVar, rhs) } DFVariableImpl *DFConstant::operator-(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.int_ = value.int_ - casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ - casted.value.uint_; - break; - case FLOAT: - val.double_ = value.double_ - casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, &type, val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SUB, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_BINARY_OP(OpType::SUB, -, newVar, rhs) } DFVariableImpl *DFConstant::operator*(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.int_ = value.int_ * casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ * casted.value.uint_; - break; - case FLOAT: - val.double_ = value.double_ * casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, &type, val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::MUL, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_BINARY_OP(OpType::MUL, *, newVar, rhs) } DFVariableImpl *DFConstant::operator/(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.int_ = value.int_ / casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ / casted.value.uint_; - break; - case FLOAT: - val.double_ = value.double_ / casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, &type, val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::DIV, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; -} + GENERIC_CONST_BINARY_OP(OpType::DIV, /, newVar, rhs) +} + +#define GENERIC_CONST_BITWISE_OP(OP_TYPE, OP, VAR, RHS) \ +DFVariableImpl *VAR; \ +if (RHS.isConstant()) { \ + Value val {}; \ + DFConstant &casted = (DFConstant &) (RHS); \ + val.uint_ = value.uint_ OP casted.value.uint_; \ + VAR = meta.varBuilder.buildConstant(meta, &type, val); \ + meta.storage.addVariable(VAR); \ + meta.graph.addNode(VAR, OpType::CONST, NodeData {}); \ + return VAR; \ +} \ +VAR = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); \ +meta.storage.addVariable(VAR); \ +meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ +meta.graph.addChannel(this, VAR, 0, false); \ +meta.graph.addChannel(&RHS, VAR, 1, false); \ +return VAR; DFVariableImpl *DFConstant::operator&(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.int_ = value.int_ & casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ & casted.value.uint_; - break; - case FLOAT: - // TODO: For discussion. - // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). - break; - } - newVar = meta.varBuilder.buildConstant(meta, &type, val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::AND, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_BITWISE_OP(OpType::AND, &, newVar, rhs) } DFVariableImpl *DFConstant::operator|(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.int_ = value.int_ | casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ | casted.value.uint_; - break; - case FLOAT: - // TODO: For discussion. - // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). - break; - } - newVar = meta.varBuilder.buildConstant(meta, &type, val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::OR, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_BITWISE_OP(OpType::OR, |, newVar, rhs) } DFVariableImpl *DFConstant::operator^(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.int_ = value.int_ | casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ | casted.value.uint_; - break; - case FLOAT: - // TODO: For discussion. - // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). - break; - } - newVar = meta.varBuilder.buildConstant(meta, &type, val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::XOR, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_BITWISE_OP(OpType::XOR, ^, newVar, rhs) } DFVariableImpl *DFConstant::operator!() { DFVariableImpl *newVar; - Value val{}; - switch (kind) { - case INT: - val.int_ = ~value.int_; - break; - case UINT: - val.uint_ = ~value.uint_; - break; - case FLOAT: - // TODO: For discussion. - // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). - break; - } + Value val {}; + val.uint_ = ~value.uint_; newVar = meta.varBuilder.buildConstant(meta, &type, val); meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NOT, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addNode(newVar, OpType::CONST, NodeData {}); return newVar; } DFVariableImpl *DFConstant::operator-() { DFVariableImpl *newVar; - Value val{}; + Value val {}; switch (kind) { case INT: val.int_ = -value.int_; @@ -263,242 +133,84 @@ DFVariableImpl *DFConstant::operator-() { } newVar = meta.varBuilder.buildConstant(meta, &type, val); meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NEG, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - return newVar; -} + meta.graph.addNode(newVar, OpType::CONST, NodeData {}); + return newVar; +} + +#define GENERIC_CONST_COMP_OP(OP_TYPE, OP, VAR, TYPE_VAR, RHS) \ +DFVariableImpl *VAR; \ +if (RHS.isConstant()) { \ + Value val {}; \ + DFConstant &casted = (DFConstant &) (RHS); \ + switch (kind) { \ + case INT: \ + val.int_ = value.int_ OP casted.value.int_; \ + break; \ + case UINT: \ + val.uint_ = value.uint_ OP casted.value.uint_; \ + break; \ + case FLOAT: \ + val.double_ = value.double_ OP casted.value.double_; \ + break; \ + } \ + VAR = meta.varBuilder.buildConstant(meta, &type, val); \ + meta.storage.addVariable(VAR); \ + meta.graph.addNode(VAR, OpType::CONST, NodeData {}); \ + return VAR; \ +} \ +DFTypeImpl *TYPE_VAR = meta.storage.addType(meta.typeBuilder.buildBool()); \ +VAR = meta.varBuilder.buildStream("", IODirection::NONE, meta, TYPE_VAR); \ +meta.storage.addVariable(VAR); \ +meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ +meta.graph.addChannel(this, VAR, 0, false); \ +meta.graph.addChannel(&RHS, VAR, 1, false); \ +return VAR; DFVariableImpl *DFConstant::operator<(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.uint_ = value.int_ < casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ < casted.value.uint_; - break; - case FLOAT: - val.uint_ = value.double_ < casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, - newType, - val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - newType); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::LESS, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_COMP_OP(OpType::LESS, <, newVar, newType, rhs) } DFVariableImpl *DFConstant::operator<=(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.uint_ = value.int_ <= casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ <= casted.value.uint_; - break; - case FLOAT: - val.uint_ = value.double_ <= casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, - newType, - val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - newType); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::LESSEQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_COMP_OP(OpType::LESSEQ, <=, newVar, newType, rhs) } DFVariableImpl *DFConstant::operator>(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.uint_ = value.int_ > casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ > casted.value.uint_; - break; - case FLOAT: - val.uint_ = value.double_ > casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, - newType, - val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - newType); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::GREATER, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_COMP_OP(OpType::GREATER, >, newVar, newType, rhs) } DFVariableImpl *DFConstant::operator>=(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.uint_ = value.int_ >= casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ >= casted.value.uint_; - break; - case FLOAT: - val.uint_ = value.double_ >= casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, - newType, - val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - newType); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::GREATEREQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_COMP_OP(OpType::GREATEREQ, >=, newVar, newType, rhs) } DFVariableImpl *DFConstant::operator==(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.uint_ = value.int_ == casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ == casted.value.uint_; - break; - case FLOAT: - val.uint_ = value.double_ == casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, - newType, - val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - newType); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::EQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_COMP_OP(OpType::EQ, ==, newVar, newType, rhs) } DFVariableImpl *DFConstant::operator!=(DFVariableImpl &rhs) { - DFVariableImpl *newVar; - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - if (rhs.isConstant()) { - Value val{}; - DFConstant &casted = (DFConstant &) (rhs); - switch (kind) { - case INT: - val.uint_ = value.int_ != casted.value.int_; - break; - case UINT: - val.uint_ = value.uint_ != casted.value.uint_; - break; - case FLOAT: - val.uint_ = value.double_ != casted.value.double_; - break; - } - newVar = meta.varBuilder.buildConstant(meta, - newType, - val); - } else { - newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, - newType); - } - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NEQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_CONST_COMP_OP(OpType::NEQ, !=, newVar, newType, rhs) } DFVariableImpl *DFConstant::operator<<(uint8_t bits) { DFVariableImpl *newVar; - Value val{}; - switch (kind) { - case INT: - val.int_ = value.int_ << bits; - break; - case UINT: - val.uint_ = value.uint_ << bits; - break; - case FLOAT: - // TODO: For discussion. - // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). - break; - } + Value val {}; + val.uint_ = value.uint_ << bits; DFTypeImpl *newType = meta.storage.addType( meta.typeBuilder.buildShiftedType(&type, bits)); newVar = meta.varBuilder.buildConstant(meta, newType, val); meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); - meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addNode(newVar, OpType::CONST, NodeData {.bitShift=bits}); return newVar; } DFVariableImpl *DFConstant::operator>>(uint8_t bits) { DFVariableImpl *newVar; - Value val{}; - switch (kind) { - case INT: - val.int_ = value.int_ >> bits; - break; - case UINT: - val.uint_ = value.uint_ >> bits; - break; - case FLOAT: - // TODO: For discussion. - // Issue #12 (https://github.com/ispras/utopia-hls/issues/12). - break; - } + Value val {}; + val.uint_ = value.uint_ >> bits; DFTypeImpl *newType = meta.storage.addType( meta.typeBuilder.buildShiftedType(&type, int8_t(bits) * -1)); newVar = meta.varBuilder.buildConstant(meta, newType, val); meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); - meta.graph.addChannel(this, newVar, 0, false); + meta.graph.addNode(newVar, OpType::CONST, NodeData {.bitShift=bits}); return newVar; } diff --git a/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp b/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp index 4097ba8..cf63718 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/scalar.cpp @@ -23,158 +23,91 @@ DFTypeImpl *DFScalar::getType() { return &type; } +#define GENERIC_STREAM_BINARY_OP(OP_TYPE, VAR, RHS) \ +DFVariableImpl *VAR = \ + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); \ +meta.storage.addVariable(VAR); \ +meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ +meta.graph.addChannel(this, VAR, 0, false); \ +meta.graph.addChannel(&RHS, VAR, 1, false); \ +return VAR; + DFVariableImpl *DFScalar::operator+(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::ADD, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::ADD, newVar, rhs) } DFVariableImpl *DFScalar::operator-(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SUB, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::SUB, newVar, rhs) } DFVariableImpl *DFScalar::operator*(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::MUL, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::MUL, newVar, rhs) } DFVariableImpl *DFScalar::operator/(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::DIV, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::DIV, newVar, rhs) } DFVariableImpl *DFScalar::operator&(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::AND, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::AND, newVar, rhs) } DFVariableImpl *DFScalar::operator|(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::OR, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::OR, newVar, rhs) } DFVariableImpl *DFScalar::operator^(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::XOR, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::XOR, newVar, rhs) } +#define GENERIC_STREAM_UNARY_OP(OP_TYPE, VAR) \ +DFVariableImpl *VAR = \ + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); \ +meta.storage.addVariable(VAR); \ +meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ +meta.graph.addChannel(this, VAR, 0, false); \ +return VAR; + DFVariableImpl *DFScalar::operator!() { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NOT, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - return newVar; + GENERIC_STREAM_UNARY_OP(OpType::NOT, newVar) } DFVariableImpl *DFScalar::operator-() { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NEG, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - return newVar; + GENERIC_STREAM_UNARY_OP(OpType::NEG, newVar) } +#define GENERIC_STREAM_COMP_OP(OP_TYPE, VAR, TYPE_VAR, RHS) \ +DFTypeImpl *TYPE_VAR = meta.storage.addType(meta.typeBuilder.buildBool()); \ + DFVariableImpl *VAR = \ + meta.varBuilder.buildStream("", IODirection::NONE, meta, TYPE_VAR); \ + meta.storage.addVariable(VAR); \ + meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ + meta.graph.addChannel(this, VAR, 0, false); \ + meta.graph.addChannel(&RHS, VAR, 1, false); \ + return VAR; + DFVariableImpl *DFScalar::operator<(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::LESS, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::LESS, newVar, newType, rhs) } DFVariableImpl *DFScalar::operator<=(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::LESSEQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::LESSEQ, newVar, newType, rhs) } DFVariableImpl *DFScalar::operator>(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::GREATER, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::GREATER, newVar, newType, rhs) } DFVariableImpl *DFScalar::operator>=(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::GREATEREQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::GREATEREQ, newVar, newType, rhs) } DFVariableImpl *DFScalar::operator==(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::EQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::EQ, newVar, newType, rhs) } DFVariableImpl *DFScalar::operator!=(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NEQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::NEQ, newVar, newType, rhs) } DFVariableImpl *DFScalar::operator<<(uint8_t bits) { @@ -183,7 +116,7 @@ DFVariableImpl *DFScalar::operator<<(uint8_t bits) { DFVariableImpl *newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); + meta.graph.addNode(newVar, OpType::SHL, NodeData {.bitShift=bits}); meta.graph.addChannel(this, newVar, 0, false); return newVar; } @@ -194,7 +127,7 @@ DFVariableImpl *DFScalar::operator>>(uint8_t bits) { DFVariableImpl *newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); + meta.graph.addNode(newVar, OpType::SHR, NodeData {.bitShift=bits}); meta.graph.addChannel(this, newVar, 0, false); return newVar; } diff --git a/src/model/dfcxx/lib/dfcxx/vars/stream.cpp b/src/model/dfcxx/lib/dfcxx/vars/stream.cpp index fda20f6..1cd8891 100644 --- a/src/model/dfcxx/lib/dfcxx/vars/stream.cpp +++ b/src/model/dfcxx/lib/dfcxx/vars/stream.cpp @@ -23,158 +23,91 @@ DFTypeImpl *DFStream::getType() { return &type; } +#define GENERIC_STREAM_BINARY_OP(OP_TYPE, VAR, RHS) \ +DFVariableImpl *VAR = \ + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); \ +meta.storage.addVariable(VAR); \ +meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ +meta.graph.addChannel(this, VAR, 0, false); \ +meta.graph.addChannel(&RHS, VAR, 1, false); \ +return VAR; + DFVariableImpl *DFStream::operator+(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::ADD, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::ADD, newVar, rhs) } DFVariableImpl *DFStream::operator-(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SUB, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::SUB, newVar, rhs) } DFVariableImpl *DFStream::operator*(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::MUL, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::MUL, newVar, rhs) } DFVariableImpl *DFStream::operator/(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::DIV, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::DIV, newVar, rhs) } DFVariableImpl *DFStream::operator&(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::AND, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::AND, newVar, rhs) } DFVariableImpl *DFStream::operator|(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::OR, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::OR, newVar, rhs) } DFVariableImpl *DFStream::operator^(DFVariableImpl &rhs) { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::XOR, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_BINARY_OP(OpType::XOR, newVar, rhs) } +#define GENERIC_STREAM_UNARY_OP(OP_TYPE, VAR) \ +DFVariableImpl *VAR = \ + meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); \ +meta.storage.addVariable(VAR); \ +meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ +meta.graph.addChannel(this, VAR, 0, false); \ +return VAR; + DFVariableImpl *DFStream::operator!() { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NOT, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - return newVar; + GENERIC_STREAM_UNARY_OP(OpType::NOT, newVar) } DFVariableImpl *DFStream::operator-() { - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, &type); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NEG, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - return newVar; + GENERIC_STREAM_UNARY_OP(OpType::NEG, newVar) } +#define GENERIC_STREAM_COMP_OP(OP_TYPE, VAR, TYPE_VAR, RHS) \ +DFTypeImpl *TYPE_VAR = meta.storage.addType(meta.typeBuilder.buildBool()); \ + DFVariableImpl *VAR = \ + meta.varBuilder.buildStream("", IODirection::NONE, meta, TYPE_VAR); \ + meta.storage.addVariable(VAR); \ + meta.graph.addNode(VAR, OP_TYPE, NodeData {}); \ + meta.graph.addChannel(this, VAR, 0, false); \ + meta.graph.addChannel(&RHS, VAR, 1, false); \ + return VAR; + DFVariableImpl *DFStream::operator<(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::LESS, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::LESS, newVar, newType, rhs) } DFVariableImpl *DFStream::operator<=(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::LESSEQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::LESSEQ, newVar, newType, rhs) } DFVariableImpl *DFStream::operator>(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::GREATER, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::GREATER, newVar, newType, rhs) } DFVariableImpl *DFStream::operator>=(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::GREATEREQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::GREATEREQ, newVar, newType, rhs) } DFVariableImpl *DFStream::operator==(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::EQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::EQ, newVar, newType, rhs) } DFVariableImpl *DFStream::operator!=(DFVariableImpl &rhs) { - DFTypeImpl *newType = meta.storage.addType(meta.typeBuilder.buildBool()); - DFVariableImpl *newVar = - meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); - meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::NEQ, NodeData{}); - meta.graph.addChannel(this, newVar, 0, false); - meta.graph.addChannel(&rhs, newVar, 1, false); - return newVar; + GENERIC_STREAM_COMP_OP(OpType::NEQ, newVar, newType, rhs) } DFVariableImpl *DFStream::operator<<(uint8_t bits) { @@ -183,7 +116,7 @@ DFVariableImpl *DFStream::operator<<(uint8_t bits) { DFVariableImpl *newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SHL, NodeData{.bitShift=bits}); + meta.graph.addNode(newVar, OpType::SHL, NodeData {.bitShift=bits}); meta.graph.addChannel(this, newVar, 0, false); return newVar; } @@ -194,7 +127,7 @@ DFVariableImpl *DFStream::operator>>(uint8_t bits) { DFVariableImpl *newVar = meta.varBuilder.buildStream("", IODirection::NONE, meta, newType); meta.storage.addVariable(newVar); - meta.graph.addNode(newVar, OpType::SHR, NodeData{.bitShift=bits}); + meta.graph.addNode(newVar, OpType::SHR, NodeData {.bitShift=bits}); meta.graph.addChannel(this, newVar, 0, false); return newVar; } diff --git a/src/options.h b/src/options.h index 19a95a7..879c972 100644 --- a/src/options.h +++ b/src/options.h @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -185,7 +184,7 @@ struct HlsOptions final : public AppOptions { // Named options. options->add_option(CONFIG_ARG, - latConfigFile, + latencyCfgFile, "JSON latency configuration path") ->expected(1); @@ -217,7 +216,7 @@ struct HlsOptions final : public AppOptions { } void fromJson(Json json) override { - get(json, CONFIG_JSON, latConfigFile); + get(json, CONFIG_JSON, latencyCfgFile); get(json, ASAP_SCHEDULER_JSON, asapScheduler); get(json, LP_SCHEDULER_JSON, lpScheduler); get(json, OUT_SV_JSON, outNames[OUT_FORMAT_ID_INT(SystemVerilog)]); @@ -262,16 +261,16 @@ struct HlsOptions final : public AppOptions { } void parseLatencyConfig() { - std::ifstream in(latConfigFile); + std::ifstream in(latencyCfgFile); if (!in.good()) { return; } auto json = Json::parse(in); for (auto &[key, val] : json.items()) { - latConfig[convertFieldToEnum(key)] = val; + latencyCfg[convertFieldToEnum(key)] = val; } } - std::string latConfigFile; - DFLatencyConfig latConfig; + std::string latencyCfgFile; + DFLatencyConfig latencyCfg; std::vector outNames; bool asapScheduler; bool lpScheduler; @@ -292,8 +291,8 @@ struct SimOptions final : public AppOptions { } void fromJson(Json json) override { - get(json, SIM_IN_JSON, inFilePath); - get(json, SIM_OUT_JSON, outFilePath); + get(json, SIM_IN_JSON, inFilePath); + get(json, SIM_OUT_JSON, outFilePath); } std::string inFilePath; From fd31d82c6d28eaea8b3f0a0ee52090f03121b331 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Tue, 27 Aug 2024 18:42:24 +0300 Subject: [PATCH 18/21] README.md restructuring. --- README.md | 71 +++--------------------------------------- docs/latency_config.md | 35 +++++++++++++++++++++ docs/simulation.md | 32 +++++++++++++++++++ 3 files changed, 71 insertions(+), 67 deletions(-) create mode 100644 docs/latency_config.md create mode 100644 docs/simulation.md diff --git a/README.md b/README.md index 0e9948c..9ab2b78 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,7 @@ Unless neither of the three arguments is used, first argument is the mode which `hls` mode is used to translate the provided DFCxx kernel to different output formats. The list of arguments for `hls`-mode is presented below: * `-h,--help`: *optional* flag; used to print the help-message about other arguments. -* `--config `: *required* filesystem-path option; used to specify the file for a JSON latency configuration file. Its format is presented in *JSON Configuration* section. +* `--config `: *required* filesystem-path option; used to specify the file for a JSON latency configuration file. Its format is presented in `docs/latency_config.md`. * `--out-sv `: *optional* filesystem-path option; used to specify the output SystemVerilog file. * `--out-sv-lib `: *optional* filesystem-path option; used to specify the output SystemVerilog file for generated operations library. * `--out-dfcir `: *optional* filesystem-path option; used to specify the output DFCIR file. @@ -235,73 +235,10 @@ umain hls --config ~/utopia-user/config.json --out-sv ~/outFile.sv --out-dfcir ~ `sim` mode is used to simulate the provided DFCxx kernel. The list of arguments for `sim`-mode is presented below: * `-h,--help`: *optional* flag; used to print the help-message about other arguments. -* `--in `: *optional* filesystem-path option; used to specify the input file for simulation data (default: `sim.txt`). Its format is presented in *DFCxx Simulation Input Format* section. +* `--in `: *optional* filesystem-path option; used to specify the input file for simulation data (default: `sim.txt`). Its format is presented in `docs/simulation.md`. * `--out `: *optional* filesystem-path option; used to specify the output VCD file (default: `sim_out.vcd`). -### JSON Configuration - -Latency configuration for each computational operation (number of pipeline stages) used in a DFCxx kernel is provided via a JSON file. - -Currently each operation has two specifications: for integer values (`INT`) and floating point (`FLOAT`) values. - -The list of all computational operations is provided below: - -* `ADD` - Addition -* `SUB` - Subtraction -* `MUL` - Multiplication -* `DIV` - Division -* `AND` - Logical conjunction -* `OR` - Logical disjunction -* `XOR` - Exclusive logical disjunction -* `NOT` - Logical inversion -* `NEG` - Negation -* `LESS` - "less" comparison -* `LESSEQ` - "less or equal" comparison -* `GREATER` - "greater" comparison -* `GREATEREQ` - "greater or equal" comparison -* `EQ` - "equal" comparison -* `NEQ` - "not equal" comparison - -JSON configuration structure states that for every operation with a specific configuration (each pair is represented as a separate JSON-field with `_` between pair's elements) present in the kernel, operation's latency will be provided. - -Here is an example of a JSON configuration file, containing latencies for multiplication, addition and subtraction of integer numbers: - -```json -{ - "MUL_INT": 3, - "ADD_INT": 1, - "SUB_INT": 1 -} -``` - -### DFCxx Simulation Input Format - -DFCxx kernels can be simulated to check that they describe computations as expected. The simulation doesn't include scheduling-related characteristics, thus DFCxx concepts like *offsets* are not supported, every computational node has to use **and** accept some value. -The format to provide simulation input data is the following: - -* input data is divided into blocks separated with a newline character (`\n`) - one block for each clock period -* every block has a number of lines, each of which has the name of some **input** stream/scalar value and its hex-value (these values do not have a type - it is assumed from the corresponding computational nodes) -* stream/scalar value name and the value are separated with a single space character (` `) -* the provided value must be a valid hex-value: with or without `0x`, with either lower- or uppercase letters -* if some stream/scalar value is present twice or more in the same block - its latest described value is used -* after the last block **no newline character can be present** - -Here is an example of an input simulation file for `MuxMul` kernel, which has two input streams `x` and `ctrl`. - -```txt -x 0x32 -ctrl 0x1 - -x 0x45 -ctrl 0x0 - -x 0x56 -ctrl 0x1 -``` - -In this example, `x` accepts values `50` (`0x32`), `69` (`0x45`) and `86` (`0x56`), while `ctrl` accepts `1`, `0` and `1`. This means that 3 clock periods will be simulated for the provided kernel. - -## Examples +### Examples Root subdirectory `examples` contains different examples of DFCxx kernels, `start`-function definitions and JSON configuration files. @@ -323,7 +260,7 @@ The same kernel can be simulated with: build/src/umain sim --in examples/polynomial2/sim.txt --out output.vcd ``` -This command uses the simulation data from `sim.txt` file to output a VCD-file `output.vcd`. +This command uses the simulation data from `sim.txt` file and stores the simulation trace in the output file `output.vcd`. ## DFCxx Documentation diff --git a/docs/latency_config.md b/docs/latency_config.md new file mode 100644 index 0000000..8f8595e --- /dev/null +++ b/docs/latency_config.md @@ -0,0 +1,35 @@ +## JSON Configuration + +Latency configuration for each computational operation (number of pipeline stages) used in a DFCxx kernel is provided via a JSON file. + +Currently each operation has two specifications: for integer values (`INT`) and floating point (`FLOAT`) values. + +The list of all computational operations is provided below: + +* `ADD` - Addition +* `SUB` - Subtraction +* `MUL` - Multiplication +* `DIV` - Division +* `AND` - Logical conjunction +* `OR` - Logical disjunction +* `XOR` - Exclusive logical disjunction +* `NOT` - Logical inversion +* `NEG` - Negation +* `LESS` - "less" comparison +* `LESSEQ` - "less or equal" comparison +* `GREATER` - "greater" comparison +* `GREATEREQ` - "greater or equal" comparison +* `EQ` - "equal" comparison +* `NEQ` - "not equal" comparison + +JSON configuration structure states that for every operation with a specific configuration (each pair is represented as a separate JSON-field with `_` between pair's elements) present in the kernel, operation's latency will be provided. + +Here is an example of a JSON configuration file, containing latencies for multiplication, addition and subtraction of integer numbers: + +```json +{ + "MUL_INT": 3, + "ADD_INT": 1, + "SUB_INT": 1 +} +``` diff --git a/docs/simulation.md b/docs/simulation.md new file mode 100644 index 0000000..ceeaca2 --- /dev/null +++ b/docs/simulation.md @@ -0,0 +1,32 @@ +## DFCxx Simulation + +DFCxx kernels can be simulated to check that they describe computations as expected. The simulation doesn't take scheduling into account and requires every computational node to use **and** accept some values at every simulation tick. + +### Input format + +The format to provide simulation input data is the following: + +* input data is divided into blocks separated with a newline character (`\n`) - one block for each simulation step +* every block has a number of lines, each of which has the name of some **input** stream/scalar value and its hex-value (these values do not have an explicit type - they will be casted to the types of related computational nodes) +* stream/scalar value name and the hex-value are separated with a single space character (` `) +* the provided value must be a valid hex-value: with or without `0x`, with either lower- or uppercase letters +* if some stream/scalar hex-value is present twice or more in the same block - its latest described value is used + +Here is an example of an input simulation file for `MuxMul` kernel, which has two input streams `x` (unsigned 32-bit integer values) and `ctrl` (unsigned 1-bit integer values -> boolean values). + +```txt +x 0x32 +ctrl 0x1 + +x 0x45 +ctrl 0x0 + +x 0x56 +ctrl 0x1 +``` + +In this example, `x` accepts values `50` (`0x32`), `69` (`0x45`) and `86` (`0x56`), while `ctrl` accepts `1`, `0` and `1`. This means that 3 simulation ticks will be performed for the provided kernel. + +### Not Supported Constructions + +* *offsets* \ No newline at end of file From 2a829bf91c9d498f796b12e0f876bcaae5133710 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Tue, 3 Sep 2024 18:09:14 +0300 Subject: [PATCH 19/21] Fixes regarding Pull Request comments. --- README.md | 4 ++-- docs/latency_config.md | 8 ++++---- docs/simulation.md | 4 ++-- src/model/dfcxx/include/dfcxx/vars/var.h | 2 +- src/model/dfcxx/lib/dfcxx/graph.cpp | 6 ++---- src/model/dfcxx/lib/dfcxx/simulator.cpp | 12 ++++++------ 6 files changed, 17 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 9ab2b78..c6a09d5 100644 --- a/README.md +++ b/README.md @@ -213,7 +213,7 @@ For the executable there are three general arguments: `-h,--help`, `-H,--help-al Unless neither of the three arguments is used, first argument is the mode which the executable has to function in. Currently there are only two available modes: `hls` and `sim`. -`hls` mode is used to translate the provided DFCxx kernel to different output formats. The list of arguments for `hls`-mode is presented below: +`hls` mode is used to perform the high-level synthesis of digital hardware description from the input DFCxx kernel. The list of arguments for `hls`-mode is presented below: * `-h,--help`: *optional* flag; used to print the help-message about other arguments. * `--config `: *required* filesystem-path option; used to specify the file for a JSON latency configuration file. Its format is presented in `docs/latency_config.md`. @@ -232,7 +232,7 @@ Here is an example of an Utopia HLS CLI call: umain hls --config ~/utopia-user/config.json --out-sv ~/outFile.sv --out-dfcir ~/outFile2.mlir -a ``` -`sim` mode is used to simulate the provided DFCxx kernel. The list of arguments for `sim`-mode is presented below: +`sim` mode is used to simulate the input DFCxx kernel. The list of arguments for `sim`-mode is presented below: * `-h,--help`: *optional* flag; used to print the help-message about other arguments. * `--in `: *optional* filesystem-path option; used to specify the input file for simulation data (default: `sim.txt`). Its format is presented in `docs/simulation.md`. diff --git a/docs/latency_config.md b/docs/latency_config.md index 8f8595e..f9fc7ca 100644 --- a/docs/latency_config.md +++ b/docs/latency_config.md @@ -1,10 +1,10 @@ ## JSON Configuration -Latency configuration for each computational operation (number of pipeline stages) used in a DFCxx kernel is provided via a JSON file. +Latency configuration (in terms of pipeline stages) for each computational operation used in a DFCxx kernel is provided via a JSON file. -Currently each operation has two specifications: for integer values (`INT`) and floating point (`FLOAT`) values. +Currently each operation has two specifications based on the types of its arguments: for integer values (`INT`) and floating point (`FLOAT`) values respectively. -The list of all computational operations is provided below: +All the supported computational operations are listed below: * `ADD` - Addition * `SUB` - Subtraction @@ -22,7 +22,7 @@ The list of all computational operations is provided below: * `EQ` - "equal" comparison * `NEQ` - "not equal" comparison -JSON configuration structure states that for every operation with a specific configuration (each pair is represented as a separate JSON-field with `_` between pair's elements) present in the kernel, operation's latency will be provided. +JSON configuration structure states that for every operation with a specific configuration (each pair is represented as a separate JSON-field with `_` between pair's elements) present in the kernel, operation's latency has to be provided. Here is an example of a JSON configuration file, containing latencies for multiplication, addition and subtraction of integer numbers: diff --git a/docs/simulation.md b/docs/simulation.md index ceeaca2..d4cdc56 100644 --- a/docs/simulation.md +++ b/docs/simulation.md @@ -7,12 +7,12 @@ DFCxx kernels can be simulated to check that they describe computations as expec The format to provide simulation input data is the following: * input data is divided into blocks separated with a newline character (`\n`) - one block for each simulation step -* every block has a number of lines, each of which has the name of some **input** stream/scalar value and its hex-value (these values do not have an explicit type - they will be casted to the types of related computational nodes) +* every block has a number of lines, each of which has the case-sensitive name of some **input** stream/scalar variable and its hex-value (these values do not have an explicit type - they will be casted to the types of related computational nodes) * stream/scalar value name and the hex-value are separated with a single space character (` `) * the provided value must be a valid hex-value: with or without `0x`, with either lower- or uppercase letters * if some stream/scalar hex-value is present twice or more in the same block - its latest described value is used -Here is an example of an input simulation file for `MuxMul` kernel, which has two input streams `x` (unsigned 32-bit integer values) and `ctrl` (unsigned 1-bit integer values -> boolean values). +Here is an example of an input simulation file for `MuxMul` kernel, which has two input streams: `x` (unsigned 32-bit integer values) and `ctrl` (unsigned 1-bit integer values). ```txt x 0x32 diff --git a/src/model/dfcxx/include/dfcxx/vars/var.h b/src/model/dfcxx/include/dfcxx/vars/var.h index 0bbffd3..6ab7533 100644 --- a/src/model/dfcxx/include/dfcxx/vars/var.h +++ b/src/model/dfcxx/include/dfcxx/vars/var.h @@ -23,7 +23,7 @@ class DFVariableImpl { friend VarBuilder; public: - enum IODirection{ + enum IODirection { NONE = 0, INPUT, OUTPUT diff --git a/src/model/dfcxx/lib/dfcxx/graph.cpp b/src/model/dfcxx/lib/dfcxx/graph.cpp index 44d4c4f..447a5e7 100644 --- a/src/model/dfcxx/lib/dfcxx/graph.cpp +++ b/src/model/dfcxx/lib/dfcxx/graph.cpp @@ -20,13 +20,11 @@ const std::unordered_set &Graph::getStartNodes() const { return startNodes; } -const std::unordered_map> &Graph::getInputs() const { +const std::unordered_map> &Graph::getInputs() const { return inputs; } -const std::unordered_map> &Graph::getOutputs() const { +const std::unordered_map> &Graph::getOutputs() const { return outputs; } diff --git a/src/model/dfcxx/lib/dfcxx/simulator.cpp b/src/model/dfcxx/lib/dfcxx/simulator.cpp index ed98f60..477169b 100644 --- a/src/model/dfcxx/lib/dfcxx/simulator.cpp +++ b/src/model/dfcxx/lib/dfcxx/simulator.cpp @@ -261,12 +261,12 @@ static inline std::string valueToBinary(SimValue value, uint64_t width) { return stream.str(); } -void DFCXXSimulator::writeOutput(ctemplate::TemplateDictionary *dict, - const RecordedValues &vals, - uint64_t startInd, - uint64_t iter, - const std::unordered_map &idMap) { +void +DFCXXSimulator::writeOutput(ctemplate::TemplateDictionary *dict, + const RecordedValues &vals, + uint64_t startInd, + uint64_t iter, + const std::unordered_map &idMap) { ctemplate::TemplateDictionary *tick = dict->AddSectionDictionary("TICKS"); tick->SetValue("TICK", std::to_string(startInd + iter)); From 8eb9020f8c2fce378df8229aa3e3184461d010b5 Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Thu, 5 Sep 2024 14:34:39 +0300 Subject: [PATCH 20/21] Fixes regarding Pull Request comments. --- README.md | 2 +- docs/latency_config.md | 4 ++-- src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c6a09d5..dfb5484 100644 --- a/README.md +++ b/README.md @@ -250,7 +250,7 @@ cmake --build build build/src/umain hls --config examples/polynomial2/add_int_2_mul_int3.json -a --out-sv output ``` -The execution command is going to pass a JSON configuration file (with 2 and 3 pipeline stages for integer addition +The execution command is going to pass a JSON configuration file (with latencies 2 and 3 for integer addition and multiplication respectively) to Utopia HLS, resulting in the creation of the file `output`, containing a SystemVerilog module for `Polynomial2` kernel with a greedy ASAP-scheduling. diff --git a/docs/latency_config.md b/docs/latency_config.md index f9fc7ca..63f9b76 100644 --- a/docs/latency_config.md +++ b/docs/latency_config.md @@ -1,6 +1,6 @@ -## JSON Configuration +## Latency Configuration -Latency configuration (in terms of pipeline stages) for each computational operation used in a DFCxx kernel is provided via a JSON file. +Latency configuration is a JSON-based file describing characteristics of computational operations for the specific DFCxx kernel. Currently each operation has two specifications based on the types of its arguments: for integer values (`INT`) and floating point (`FLOAT`) values respectively. diff --git a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp index dd2ebe8..7b58258 100644 --- a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp @@ -271,7 +271,7 @@ void DFCIRBuilder::translate(Node node, const Graph &graph, map[first], attr); break; } - default: assert(false); + default: assert(false && "Unknown node type"); } map[node] = newOp->getResult(0); From 97d413de6cd3bf56637768965b42e4b7a173927e Mon Sep 17 00:00:00 2001 From: Muxianesty Date: Thu, 5 Sep 2024 14:45:12 +0300 Subject: [PATCH 21/21] Unknown node type logging in builder.cpp added. --- src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp index 7b58258..2dffc35 100644 --- a/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp +++ b/src/model/dfcxx/lib/dfcxx/IRbuilders/builder.cpp @@ -11,6 +11,8 @@ #include "mlir/Parser/Parser.h" +#include + namespace dfcxx { DFCIRBuilder::DFCIRBuilder() : ctx(), conv(&ctx) { @@ -271,7 +273,11 @@ void DFCIRBuilder::translate(Node node, const Graph &graph, map[first], attr); break; } - default: assert(false && "Unknown node type"); + default: { + // TODO: Add proper logging: https://github.com/ispras/utopia-hls/issues/13 + std::cout << "[ERROR] Unknown node type id: " << node.type << std::endl; + assert(false); + }; } map[node] = newOp->getResult(0);