Jeremy Grosser 5 лет назад
Родитель
Сommit
4639e75d0d
2 измененных файлов с 147 добавлено и 0 удалено
  1. 1 0
      tools/pioasm/CMakeLists.txt
  2. 146 0
      tools/pioasm/ada_output.cpp

+ 1 - 0
tools/pioasm/CMakeLists.txt

@@ -23,6 +23,7 @@ add_executable(pioasm
 target_sources(pioasm PRIVATE c_sdk_output.cpp)
 target_sources(pioasm PRIVATE python_output.cpp)
 target_sources(pioasm PRIVATE hex_output.cpp)
+target_sources(pioasm PRIVATE ada_output.cpp)
 target_sources(pioasm PRIVATE ${PIOASM_EXTRA_SOURCE_FILES})
 
 if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND

+ 146 - 0
tools/pioasm/ada_output.cpp

@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Ada specifications generated by this assembler depend on the RP.PIO package,
+ * available in rp2040_hal.
+ *
+ * https://github.com/JeremyGrosser/rp2040_hal
+ * https://github.com/JeremyGrosser/pico_bsp
+ * https://github.com/JeremyGrosser/pico_examples
+ */
+
+#include <algorithm>
+#include <iostream>
+#include "output_format.h"
+#include "pio_disassembler.h"
+
+struct ada_output : public output_format {
+    struct factory {
+        factory() {
+            output_format::add(new ada_output());
+        }
+    };
+
+    ada_output() : output_format("ada") {}
+
+    std::string get_description() override {
+        return "Ada specification";
+    }
+
+    void output_symbols(FILE *out, const std::vector<compiled_source::symbol> &symbols) {
+        int count = 0;
+        for (const auto &s : symbols) {
+            if (!s.is_label) {
+                fprintf(out, "%s : constant := %d;\n", s.name.c_str(), s.value);
+                count++;
+            }
+        }
+        if (count) {
+            fprintf(out, "\n");
+            count = 0;
+        }
+        for (const auto &s : symbols) {
+            if (s.is_label) {
+                fprintf(out, "   Offset_%s : constant := %d;\n", s.name.c_str(), s.value);
+                count++;
+            }
+        }
+        if (count) {
+            fprintf(out, "\n");
+        }
+    }
+
+    void ada_case(std::string &identifier) {
+        for(std::string::size_type i = 0; i < identifier.size(); ++i) {
+            if ((i == 0) || (identifier[i - 1] == '_')) {
+                identifier[i] = toupper(identifier[i]);
+            }
+        }
+    }
+
+    void header(FILE *out, const std::string msg, const int indent) {
+        const std::string dashes = std::string(msg.length() + 6, '-');
+        const std::string indent_str= std::string(indent, ' ');
+        fprintf(out, "%s%s\n", indent_str.c_str(), dashes.c_str());
+        fprintf(out, "%s-- %s --\n", indent_str.c_str(), msg.c_str());
+        fprintf(out, "%s%s\n", indent_str.c_str(), dashes.c_str());
+        fprintf(out, "\n");
+    }
+
+    int output(std::string destination, std::vector<std::string> output_options,
+               const compiled_source &source) override {
+
+        for (const auto &program : source.programs) {
+            for(const auto &p : program.lang_opts) {
+                if (p.first.size() >= name.size() && p.first.compare(0, name.size(), name) == 0) {
+                    std::cerr << "warning: " << name << " does not support output options; " << p.first << " lang_opt ignored.\n";
+                }
+            }
+        }
+
+        std::string package_name;
+
+        switch (output_options.size()) {
+            case 0:
+                std::cerr << "error: missing package name options for Ada format" << std::endl;
+                return 1;
+            case 1:
+                package_name = output_options[0]; // Package name from command options
+                break;
+            default:
+                std::cerr << "error: too many options for Ada format" << std::endl;
+                return 1;
+        }
+
+        FILE *out = open_single_output(destination);
+        if (!out) return 1;
+
+        header(out, "This file is autogenerated by pioasm; do not edit!", 0);
+        fprintf(out, "pragma Style_Checks (Off);\n\n");
+        fprintf(out, "with RP.PIO;\n\n");
+
+        fprintf(out, "package %s is\n", package_name.c_str());
+
+        for (const auto &program : source.programs) {
+            std::string trailing_comma = ", ";
+
+            std::string prog_name= program.name;
+            ada_case(prog_name);
+
+            fprintf(out, "\n");
+            header(out, prog_name, 3);
+
+
+            output_symbols(out, source.global_symbols);
+            fprintf(out, "   %s_Wrap_Target : constant := %d;\n", prog_name.c_str(), program.wrap_target);
+            fprintf(out, "   %s_Wrap        : constant := %d;\n", prog_name.c_str(), program.wrap);
+            fprintf(out, "\n");
+
+            output_symbols(out, program.symbols);
+
+            fprintf(out, "   %s_Program_Instructions : RP.PIO.Program := (\n", prog_name.c_str());
+            for (int i = 0; i < (int)program.instructions.size(); i++) {
+                const auto &inst = program.instructions[i];
+                if (i == program.wrap_target) {
+                    fprintf(out, "                    --  .wrap_target\n");
+                }
+                if (i == (int)program.instructions.size() - 1) {
+                    trailing_comma = ");";
+                }
+                fprintf(out, "         16#%04x#%s --  %2d: %s\n", inst, trailing_comma.c_str(), i,
+                        disassemble(inst, program.sideset_bits_including_opt.get(), program.sideset_opt).c_str());
+                if (i == program.wrap) {
+                    fprintf(out, "                    --  .wrap\n");
+                }
+            }
+        }
+        fprintf(out, "\n");
+        fprintf(out, "end %s;\n", package_name.c_str());
+        fclose(out);
+        return 0;
+    }
+};
+
+static ada_output::factory creator;