logic.lua 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. local lg = {}
  2. -- (de)serialize
  3. lg.serialize = function(t)
  4. local function _op(t)
  5. if t == nil then
  6. return " "
  7. elseif t.type == "io" then
  8. return t.port
  9. else -- t.type == "reg"
  10. return tostring(t.n)
  11. end
  12. end
  13. local function _action(s)
  14. if s == nil then
  15. return " "
  16. end
  17. local mapping = {
  18. ["and"] = "&",
  19. ["or"] = "|",
  20. ["not"] = "~",
  21. ["xor"] = "^",
  22. ["nand"] = "?", --dunno
  23. ["buf"] = "_",
  24. ["xnor"] = "=",
  25. }
  26. return mapping[s]
  27. end
  28. local s = ""
  29. for i = 1, 14 do
  30. local cur = t[i]
  31. if next(cur) ~= nil then
  32. s = s .. _op(cur.op1) .. _action(cur.action) .. _op(cur.op2) .. _op(cur.dst)
  33. end
  34. s = s .. "/"
  35. end
  36. return s
  37. end
  38. lg.deserialize = function(s)
  39. local function _op(c)
  40. if c == "A" or c == "B" or c == "C" or c == "D" then
  41. return {type = "io", port = c}
  42. elseif c == " " then
  43. return nil
  44. else
  45. return {type = "reg", n = tonumber(c)}
  46. end
  47. end
  48. local function _action(c)
  49. local mapping = {
  50. ["&"] = "and",
  51. ["|"] = "or",
  52. ["~"] = "not",
  53. ["^"] = "xor",
  54. ["?"] = "nand",
  55. ["_"] = "buf",
  56. ["="] = "xnor",
  57. [" "] = nil,
  58. }
  59. return mapping[c]
  60. end
  61. local ret = {}
  62. for part in s:gmatch("(.-)/") do
  63. local parsed
  64. if part == "" then
  65. parsed = {}
  66. else
  67. parsed = {
  68. action = _action( part:sub(2,2) ),
  69. op1 = _op( part:sub(1,1) ),
  70. op2 = _op( part:sub(3,3) ),
  71. dst = _op( part:sub(4,4) ),
  72. }
  73. end
  74. ret[#ret + 1] = parsed
  75. end
  76. -- More than 14 instructions (write to all 10 regs + 4 outputs)
  77. -- will not pass the write-once requirement of the validator
  78. assert(#ret == 14)
  79. return ret
  80. end
  81. -- validation
  82. lg.validate_single = function(t, i)
  83. local function is_reg_written_to(t, n, max)
  84. for i = 1, max-1 do
  85. if next(t[i]) ~= nil
  86. and t[i].dst and t[i].dst.type == "reg"
  87. and t[i].dst.n == n then
  88. return true
  89. end
  90. end
  91. return false
  92. end
  93. local function compare_op(t1, t2, allow_same_io)
  94. if t1 == nil or t2 == nil then
  95. return false
  96. elseif t1.type ~= t2.type then
  97. return false
  98. end
  99. if t1.type == "reg" and t1.n == t2.n then
  100. return true
  101. elseif t1.type == "io" and t1.port == t2.port then
  102. return not allow_same_io
  103. end
  104. return false
  105. end
  106. local elem = t[i]
  107. -- check for completeness
  108. if elem.action == nil then
  109. return {i = i, msg = "Gate type required"}
  110. elseif elem.action == "not" or elem.action == "buf" then
  111. if elem.op1 ~= nil or elem.op2 == nil or elem.dst == nil then
  112. return {i = i, msg = "Second operand (only) and destination required"}
  113. end
  114. else
  115. if elem.op1 == nil or elem.op2 == nil or elem.dst == nil then
  116. return {i = i, msg = "Operands and destination required"}
  117. end
  118. end
  119. -- check whether operands/destination are identical
  120. if compare_op(elem.op1, elem.op2) then
  121. return {i = i, msg = "Operands cannot be identical"}
  122. end
  123. if compare_op(elem.op1, elem.dst, true) or compare_op(elem.op2, elem.dst, true) then
  124. return {i = i, msg = "Destination and operands must be different"}
  125. end
  126. -- check whether operands point to defined registers
  127. if elem.op1 ~= nil and elem.op1.type == "reg"
  128. and not is_reg_written_to(t, elem.op1.n, i) then
  129. return {i = i, msg = "First operand is undefined register"}
  130. end
  131. if elem.op2.type == "reg" and not is_reg_written_to(t, elem.op2.n, i) then
  132. return {i = i, msg = "Second operand is undefined register"}
  133. end
  134. -- check whether destination points to undefined register
  135. if elem.dst.type == "reg" and is_reg_written_to(t, elem.dst.n, i) then
  136. return {i = i, msg = "Destination is already used register"}
  137. end
  138. return nil
  139. end
  140. lg.validate = function(t)
  141. for i = 1, 14 do
  142. if next(t[i]) ~= nil then
  143. local r = lg.validate_single(t, i)
  144. if r ~= nil then
  145. return r
  146. end
  147. end
  148. end
  149. return nil
  150. end
  151. -- interpreter
  152. lg.interpret = function(t, a, b, c, d)
  153. local function _action(s, v1, v2)
  154. if s == "and" then
  155. return v1 and v2
  156. elseif s == "or" then
  157. return v1 or v2
  158. elseif s == "not" then
  159. return not v2
  160. elseif s == "xor" then
  161. return v1 ~= v2
  162. elseif s == "nand" then
  163. return not (v1 and v2)
  164. elseif s == "buf" then
  165. return v2
  166. else -- s == "xnor"
  167. return v1 == v2
  168. end
  169. end
  170. local function _op(t, regs, io_in)
  171. if t.type == "reg" then
  172. return regs[t.n]
  173. else -- t.type == "io"
  174. return io_in[t.port]
  175. end
  176. end
  177. local io_in = {A=a, B=b, C=c, D=d}
  178. local regs = {}
  179. local io_out = {}
  180. for i = 1, 14 do
  181. local cur = t[i]
  182. if next(cur) ~= nil then
  183. local v1, v2
  184. if cur.op1 ~= nil then
  185. v1 = _op(cur.op1, regs, io_in)
  186. end
  187. v2 = _op(cur.op2, regs, io_in)
  188. local result = _action(cur.action, v1, v2)
  189. if cur.dst.type == "reg" then
  190. regs[cur.dst.n] = result
  191. else -- cur.dst.type == "io"
  192. io_out[cur.dst.port] = result
  193. end
  194. end
  195. end
  196. return io_out.A, io_out.B, io_out.C, io_out.D
  197. end
  198. return lg