1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _OUTPUT_FORMAT_H
8 #define _OUTPUT_FORMAT_H
9 
10 #include <vector>
11 #include <map>
12 #include <string>
13 #include <memory>
14 
15 #include "pio_enums.h"
16 
17 typedef unsigned int uint;
18 
19 // can't use optional because we want to support older compilers
20 template<typename T>
21 struct simple_optional {
22     T value;
23     T default_value;
24     bool specified;
25 
simple_optionalsimple_optional26     simple_optional() : default_value(), specified(false) {}
27 
simple_optionalsimple_optional28     simple_optional(const T &value) : value(value), specified(true) {}
29 
30     simple_optional<T> &operator=(const T &v) {
31         value = v;
32         specified = true;
33         return *this;
34     }
35 
36     operator bool() = delete; // confusing
getsimple_optional37     const T &get() const { return specified ? value : default_value; }
38 
is_specifiedsimple_optional39     bool is_specified() const { return specified; }
40 
with_defaultsimple_optional41     static simple_optional<T> with_default(const T &default_value) {
42         simple_optional<T> rc;
43         rc.default_value = default_value;
44         return rc;
45     }
46 };
47 
48 typedef simple_optional<int> optional_int;
49 typedef simple_optional<bool> optional_bool;
50 
51 struct compiled_source {
52     struct symbol {
53         std::string name;
54         int value;
55         bool is_label;
56 
symbolcompiled_source::symbol57         symbol(std::string name, int value, bool is_label) : name(std::move(name)), value(value), is_label(is_label) {}
58     };
59 
60     struct in_out {
61         int pin_count;
62         bool right;
63         bool autop;
64         int threshold;
65     };
66 
67     struct program {
68         std::string name;
69         optional_int origin = optional_int::with_default(-1);
70         optional_int sideset_bits_including_opt;
71         bool sideset_opt = false;
72         bool sideset_pindirs = false;
73         int wrap;
74         int wrap_target;
75         int pio_version;
76         int mov_status_type;
77         int mov_status_n;
78         in_out in;
79         in_out out;
80         int set_count;
81         uint clock_div_int;
82         uint clock_div_frac;
83         uint8_t used_gpio_ranges;
84         fifo_config fifo;
85         std::vector<uint> instructions;
86         std::vector<symbol> symbols; // public only
87         std::map<std::string, std::vector<std::string>> code_blocks;
88         std::map<std::string, std::vector<std::pair<std::string,std::string>>> lang_opts;
89 
90         // todo can't have wrap at -1
programcompiled_source::program91         program(std::string name) : name(std::move(name)) {}
92     };
93 
94     std::vector<symbol> global_symbols; // public only
95     std::vector<program> programs;
96 };
97 
98 struct output_format {
99     static std::string default_name;
100 
101     std::string name;
102 
addoutput_format103     static void add(output_format *lang) {
104         all().push_back(std::shared_ptr<output_format>(lang));
105     }
106 
107     virtual int output(std::string destination, std::vector<std::string> output_options,
108                        const compiled_source &source) = 0;
109 
110     virtual std::string get_description() = 0;
111 
112     FILE *open_single_output(std::string destination);
113     virtual ~output_format() = default;
114 
alloutput_format115     static std::vector<std::shared_ptr<output_format>>& all() {
116         static std::vector<std::shared_ptr<output_format>> output_formats;
117         return output_formats;
118     }
119 protected:
output_formatoutput_format120     output_format(std::string name) : name(std::move(name)) {}
121 };
122 
123 #endif