pio_types.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*
  2. * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #ifndef _PIO_TYPES_H
  7. #define _PIO_TYPES_H
  8. #include <string>
  9. #include <map>
  10. #include <set>
  11. #include <utility>
  12. #include <vector>
  13. #include <memory>
  14. #include "location.h"
  15. typedef unsigned int uint;
  16. enum struct inst_type {
  17. jmp = 0x0,
  18. wait = 0x1,
  19. in = 0x2,
  20. out = 0x3,
  21. push_pull = 0x4,
  22. mov = 0x5,
  23. irq = 0x6,
  24. set = 0x7,
  25. };
  26. /* condition codes */
  27. enum struct condition {
  28. al = 0x0,
  29. xz = 0x1,
  30. xnz__ = 0x2,
  31. yz = 0x3,
  32. ynz__ = 0x4,
  33. xney = 0x5,
  34. pin = 0x6,
  35. osrez = 0x7,
  36. };
  37. /* in source / out / set target - not all valid */
  38. enum struct in_out_set {
  39. in_out_set_pins = 0x0,
  40. in_out_set_x = 0x1,
  41. in_out_set_y = 0x2,
  42. in_out_null = 0x3,
  43. in_out_set_pindirs = 0x4,
  44. in_status = 0x5,
  45. out_set_pc = 0x5,
  46. in_out_isr = 0x6,
  47. in_osr = 0x7,
  48. out_exec = 0x7,
  49. };
  50. enum struct irq {
  51. set = 0x0,
  52. set_wait = 0x1,
  53. clear = 0x2,
  54. };
  55. // mov src/dest (not all valid)
  56. enum struct mov {
  57. pins = 0x0,
  58. x = 0x1,
  59. y = 0x2,
  60. null = 0x3,
  61. exec = 0x4,
  62. pc = 0x5,
  63. status = 0x5,
  64. isr = 0x6,
  65. osr = 0x7,
  66. };
  67. enum struct mov_op {
  68. none = 0x0,
  69. invert = 0x1,
  70. bit_reverse = 0x2,
  71. };
  72. struct src_item {
  73. yy::location location;
  74. src_item() = default;
  75. explicit src_item(const yy::location &location) : location(location) {}
  76. };
  77. struct program;
  78. struct pio_assembler;
  79. struct resolvable : public src_item {
  80. resolvable(const yy::location &l) : src_item(l) {}
  81. int resolve(const program &program);
  82. int resolve(pio_assembler *pioasm, const program *program) {
  83. return resolve(pioasm, program, *this);
  84. }
  85. virtual int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) = 0;
  86. };
  87. using rvalue = std::shared_ptr<resolvable>;
  88. struct wait_source {
  89. enum type {
  90. gpio = 0x0,
  91. pin = 0x1,
  92. irq = 0x2
  93. } target;
  94. rvalue param;
  95. bool flag;
  96. wait_source(type target, rvalue param, bool flag = false) : target(target), param(std::move(param)), flag(flag) {}
  97. };
  98. struct name_ref : public resolvable {
  99. std::string name;
  100. name_ref(const yy::location &l, std::string name) : resolvable(l), name(std::move(name)) {}
  101. int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override;
  102. };
  103. struct code_block : public resolvable {
  104. std::string lang;
  105. std::string contents;
  106. code_block(const yy::location &l, std::string lang, std::string contents) : resolvable(l), lang(std::move(lang)),
  107. contents(std::move(contents)) {}
  108. int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override {
  109. return 0;
  110. }
  111. };
  112. struct int_value : public resolvable {
  113. int value;
  114. int_value(const yy::location &l, int value) : resolvable(l), value(value) {}
  115. int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override {
  116. return value;
  117. }
  118. };
  119. static inline rvalue resolvable_int(const yy::location &l, int v) {
  120. return std::shared_ptr<resolvable>(new int_value(l, v));
  121. }
  122. struct binary_operation : public resolvable {
  123. enum op_type {
  124. add,
  125. subtract,
  126. multiply,
  127. divide,
  128. and_, // pesky C++
  129. or_,
  130. xor_
  131. };
  132. op_type op;
  133. rvalue left, right;
  134. binary_operation(const yy::location &l, op_type op, rvalue left, rvalue right) :
  135. resolvable(l), op(op), left(std::move(left)), right(std::move(right)) {}
  136. int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override;
  137. };
  138. struct unary_operation : public resolvable {
  139. enum op_type {
  140. negate,
  141. reverse
  142. };
  143. op_type op;
  144. rvalue arg;
  145. unary_operation(const yy::location &l, op_type op, const rvalue &arg) :
  146. resolvable(l), op(op), arg(arg) {}
  147. int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override;
  148. };
  149. struct symbol : public src_item {
  150. std::string name;
  151. rvalue value;
  152. bool is_public;
  153. bool is_label;
  154. int resolve_started;
  155. symbol(const yy::location &l, std::string name, bool is_extern = false) : src_item(l), name(std::move(name)),
  156. is_public(is_extern), is_label(false),
  157. resolve_started(false) {}
  158. };
  159. struct raw_encoding {
  160. enum inst_type type;
  161. uint arg1;
  162. uint arg2;
  163. };
  164. struct instruction : public src_item {
  165. rvalue sideset; // possibly null
  166. rvalue delay;
  167. instruction(const yy::location &l) : src_item(l) {}
  168. virtual uint encode(const program &program);
  169. virtual raw_encoding raw_encode(const program &program);
  170. };
  171. struct pio_assembler;
  172. // rvalue with extra encompassing location
  173. struct rvalue_loc {
  174. rvalue value;
  175. yy::location location;
  176. rvalue_loc() = default;
  177. rvalue_loc(const rvalue &v, const yy::location &l) : value(v), location(l) {}
  178. };
  179. struct program : public src_item {
  180. static const int MAX_INSTRUCTIONS = 32;
  181. pio_assembler *pioasm;
  182. std::string name;
  183. rvalue_loc origin;
  184. rvalue_loc sideset;
  185. bool sideset_opt;
  186. bool sideset_pindirs;
  187. rvalue wrap_target;
  188. rvalue wrap;
  189. std::map<std::string, std::shared_ptr<symbol>> symbols;
  190. std::vector<std::shared_ptr<symbol>> ordered_symbols;
  191. std::vector<std::shared_ptr<instruction>> instructions;
  192. std::map<std::string, std::vector<code_block>> code_blocks;
  193. std::map<std::string, std::vector<std::pair<std::string,std::string>>> lang_opts;
  194. // post finalization
  195. int delay_max;
  196. int sideset_bits_including_opt; // specified side set bits + 1 if we need presence flag
  197. int sideset_max;
  198. program(pio_assembler *pioasm, const yy::location &l, std::string name) :
  199. src_item(l), pioasm(pioasm), name(std::move(name)), sideset_opt(true), sideset_pindirs(false) {}
  200. void set_origin(const yy::location &l, const rvalue &_origin) {
  201. origin = rvalue_loc(_origin, l);
  202. }
  203. void set_wrap_target(const yy::location &l);
  204. void set_wrap(const yy::location &l);
  205. void set_sideset(const yy::location &l, rvalue _sideset, bool optional, bool pindirs) {
  206. sideset = rvalue_loc(_sideset, l);
  207. sideset_opt = optional;
  208. sideset_pindirs = pindirs;
  209. }
  210. void add_label(std::shared_ptr<symbol> label) {
  211. label->value = resolvable_int(label->location, instructions.size());
  212. add_symbol(label);
  213. }
  214. void add_symbol(std::shared_ptr<symbol> symbol);
  215. void add_instruction(std::shared_ptr<instruction> inst);
  216. void add_code_block(const code_block &block);
  217. void add_lang_opt(std::string lang, std::string name, std::string value);
  218. void finalize();
  219. };
  220. struct instr_jmp : public instruction {
  221. condition cond;
  222. rvalue target;
  223. instr_jmp(const yy::location &l, condition c, rvalue target) : instruction(l), cond(c), target(std::move(target)) { }
  224. raw_encoding raw_encode(const program &program) override;
  225. };
  226. struct instr_wait : public instruction {
  227. rvalue polarity;
  228. std::shared_ptr<wait_source> source;
  229. instr_wait(const yy::location &l, rvalue polarity, std::shared_ptr<wait_source> source) : instruction(l), polarity(
  230. std::move(polarity)), source(std::move(source)) {}
  231. raw_encoding raw_encode(const program &program) override;
  232. };
  233. struct instr_in : public instruction {
  234. enum in_out_set src;
  235. rvalue value;
  236. instr_in(const yy::location &l, const enum in_out_set &src, rvalue value) : instruction(l), src(src),
  237. value(std::move(value)) {}
  238. raw_encoding raw_encode(const program &program) override;
  239. };
  240. struct instr_out : public instruction {
  241. enum in_out_set dest;
  242. rvalue value;
  243. instr_out(const yy::location &l, const enum in_out_set &dest, rvalue value) : instruction(l), dest(dest),
  244. value(std::move(value)) {}
  245. raw_encoding raw_encode(const program &program) override;
  246. };
  247. struct instr_set : public instruction {
  248. enum in_out_set dest;
  249. rvalue value;
  250. instr_set(const yy::location &l, const enum in_out_set &dest, rvalue value) : instruction(l), dest(dest),
  251. value(std::move(value)) {}
  252. raw_encoding raw_encode(const program &program) override;
  253. };
  254. struct instr_push : public instruction {
  255. bool if_full, blocking;
  256. instr_push(const yy::location &l, bool if_full, bool blocking) : instruction(l), if_full(if_full),
  257. blocking(blocking) {}
  258. raw_encoding raw_encode(const program &program) override {
  259. uint arg1 = (blocking ? 1u : 0u) | (if_full ? 0x2u : 0);
  260. return {inst_type::push_pull, arg1, 0};
  261. }
  262. };
  263. struct instr_pull : public instruction {
  264. bool if_empty, blocking;
  265. instr_pull(const yy::location &l, bool if_empty, bool blocking) : instruction(l), if_empty(if_empty),
  266. blocking(blocking) {}
  267. raw_encoding raw_encode(const program &program) override {
  268. uint arg1 = (blocking ? 1u : 0u) | (if_empty ? 0x2u : 0) | 0x4u;
  269. return {inst_type::push_pull, arg1, 0};
  270. }
  271. };
  272. struct instr_mov : public instruction {
  273. enum mov dest, src;
  274. mov_op op;
  275. instr_mov(const yy::location &l, const enum mov &dest, const enum mov &src, const mov_op& op = mov_op::none) :
  276. instruction(l), dest(dest), src(src), op(op) {}
  277. raw_encoding raw_encode(const program &program) override {
  278. return {inst_type::mov, (uint) dest, (uint)src | ((uint)op << 3u)};
  279. }
  280. };
  281. struct instr_irq : public instruction {
  282. enum irq modifiers;
  283. rvalue num;
  284. bool relative;
  285. instr_irq(const yy::location &l, const enum irq &modifiers, rvalue num, bool relative = false) :
  286. instruction(l), modifiers(modifiers), num(std::move(num)), relative(relative) {}
  287. raw_encoding raw_encode(const program &program) override;
  288. };
  289. struct instr_nop : public instr_mov {
  290. instr_nop(const yy::location &l) : instr_mov(l, mov::y, mov::y) {}
  291. };
  292. struct instr_word : public instruction {
  293. rvalue encoding;
  294. instr_word(const yy::location &l, rvalue encoding) : instruction(l), encoding(std::move(encoding)) {}
  295. uint encode(const program &program) override;
  296. };
  297. #endif