Compare commits

...

2 Commits

6 changed files with 413 additions and 0 deletions

View File

@ -0,0 +1,52 @@
local function split_string(input_str, delimiter)
local result = {}
for match in (input_str .. delimiter):gmatch("(.-)" .. delimiter) do
table.insert(result, match)
end
return result
end
function AssembleAtomicCode(buffer)
local brainfuck_code = ""
buffer = buffer:gsub(" ", ";")
buffer = buffer:gsub("\n", ";")
buffer = buffer:gsub("\t", ";")
local tokens = split_string(buffer, ";")
local is_comment = false
for index, token in ipairs(tokens) do
if token == "##" and is_comment then
brainfuck_code = brainfuck_code .. "\n"
is_comment = false
elseif token == "##" and not is_comment then
brainfuck_code = brainfuck_code .. "\n"
is_comment = true
elseif is_comment then
brainfuck_code = brainfuck_code .. token .. " "
elseif token == "up" then
brainfuck_code = brainfuck_code .. ">"
elseif token == "down" then
brainfuck_code = brainfuck_code .. "<"
elseif token == "inc" then
brainfuck_code = brainfuck_code .. "+"
elseif token == "dec" then
brainfuck_code = brainfuck_code .. "-"
elseif token == "get" then
brainfuck_code = brainfuck_code .. ","
elseif token == "set" then
brainfuck_code = brainfuck_code .. "."
elseif token == "begin" then
brainfuck_code = brainfuck_code .. "["
elseif token == "end" then
brainfuck_code = brainfuck_code .. "]"
else
if token ~= "\0" then
print("ERROR: The token " .. token .. " is not an atomic token!" .. token)
end
end
end
return brainfuck_code
end

16
assembly/basic_logic.bf Normal file
View File

@ -0,0 +1,16 @@
## Loading cell 0 with 5 and cell 1 with 3 ##
inc inc inc inc inc
up
inc inc inc
down
## Adding cell 0 to cell 1 ##
begin
dec
up
inc
down
end
up up inc
begin end

View File

@ -0,0 +1,98 @@
function wait(seconds)
local start = os.time()
repeat
until os.time() > start + seconds
end
function CompileBrainfuck(brainfuck, target)
local machine_code = "("
if target == "vhdl" then
machine_code = "("
elseif target == "logisim" then
machine_code = "v3.0 hex words plain\n"
else
print("ERROR: Target " .. target .. " is not supported!")
end
for i = 0, #brainfuck do
local token = brainfuck:sub(i, i)
if target == "vhdl" then
if token == ">" then
machine_code = machine_code .. 'b"000",'
elseif token == "<" then
machine_code = machine_code .. 'b"001",'
elseif token == "+" then
machine_code = machine_code .. 'b"010",'
elseif token == "-" then
machine_code = machine_code .. 'b"011",'
elseif token == "," then
machine_code = machine_code .. 'b"100",'
elseif token == "." then
machine_code = machine_code .. 'b"101",'
elseif token == "[" then
machine_code = machine_code .. 'b"110",'
elseif token == "]" then
machine_code = machine_code .. 'b"111",'
end
elseif target == "logisim" then
local found_token = false
if token == ">" then
machine_code = machine_code .. "0"
found_token = true
elseif token == "<" then
machine_code = machine_code .. "1"
found_token = true
elseif token == "+" then
machine_code = machine_code .. "2"
found_token = true
elseif token == "-" then
machine_code = machine_code .. "3"
found_token = true
elseif token == "," then
machine_code = machine_code .. "4"
found_token = true
elseif token == "." then
machine_code = machine_code .. "5"
found_token = true
elseif token == "[" then
machine_code = machine_code .. "6"
found_token = true
elseif token == "]" then
machine_code = machine_code .. "7"
found_token = true
end
if found_token then
if (#machine_code - 20) % 64 == 0 then
machine_code = machine_code .. "\n"
else
machine_code = machine_code .. " "
end
end
else
print("ERROR: Target " .. target .. " is not supported!")
end
end
if target == "vhdl" then
machine_code = machine_code .. 'others => "000");\n'
elseif target == "logisim" then
while #machine_code < 533 do
machine_code = machine_code .. '0'
if (#machine_code - 20) % 64 == 0 then
machine_code = machine_code .. "\n"
else
machine_code = machine_code .. " "
end
end
else
print("ERROR: Target " .. target .. " not found!")
end
return machine_code
end

View File

@ -0,0 +1,153 @@
function AssembleComplexCode(content)
local atomic = ""
memory_pointer = 0
local state = "idle"
local instruction = {}
content = content:gsub(" ", ";")
content = content:gsub("\n", ";")
content = content:gsub("\t", ";")
local tokens = split_string(content, ";")
local is_comment = false
for index, token in ipairs(tokens) do
if token == "##" and is_comment then
atomic = atomic .. " ##\n"
is_comment = false
elseif token == "##" and not is_comment then
atomic = "## " .. atomic .. "\n"
is_comment = true
elseif is_comment then
atomic = atomic .. token .. " "
elseif state == "idle" then
state, instruction = decode_instruction(token)
elseif state == "twooperands" then
table.insert(instruction, token)
state = "oneoperand"
elseif state == "oneoperand" then
table.insert(instruction, token)
state = "handling"
elseif state == "handling" then
atomic = handle_instrcution(content, instruction)
else
if token ~= "\0" then
print("ERROR: The token " .. token .. " is not a valid instruction!")
end
end
end
return atomic
end
local function decode_instruction(operand_token)
local singop = {}
local oneop = { "loop" }
local twoop = { "add", "sub" }
if singop[operand_token] ~= nil then
return "handle", { operand_token }
elseif oneop[operand_token] ~= nil then
return "oneoperand", { operand_token }
elseif twoop[operand_token] ~= nil then
return "twooperands", { operand_token }
end
return "idle", {}
end
local function abs(number)
if number < 0 then
return number * -1
else
return number
end
end
local function get_fix_move(origin, destination)
local direction
local route = ""
if origin < destination then
direction = "up"
else
direction = "down"
end
for i = 0, abs(destination - origin) do
route = route .. direction .. " "
end
return route
end
local function handle_instrcution(content, instruction)
local atomic_code
if instruction[1] == "add" then
local reg1 = tonumber(instruction[2]:sub(2)) + 8
local reg2 = tonumber(instruction[3]:sub(2)) + 8
local old_pos = memory_pointer
atomic_code = "## ADD " .. instruction[2] .. " to " .. instruction[3] .. " ##\n"
local move_to_operation = get_fix_move(old_pos, reg1)
local reg1_to_t1 = get_fix_move(reg1, 0)
local t2_to_reg1 = get_fix_move(2, reg1)
local reg1_to_t2 = get_fix_move(reg1, 2)
local t1_to_reg2 = get_fix_move(1, reg2)
local reg2_to_t1 = get_fix_move(reg2, 1)
local t1_to_origin = get_fix_move(1, old_pos)
atomic_code = atomic_code .. move_to_operation
-- Move reg1 into t1,t2
atomic_code = atomic_code .. "begin dec " .. reg1_to_t1 .. "inc up inc " .. t2_to_reg1 .. "end "
-- Move t2 into reg1
atomic_code = atomic_code .. reg1_to_t2 .. "begin dec " .. t2_to_reg1 .. "inc " .. reg1_to_t2 .. "end "
-- Move to t1
atomic_code = atomic_code .. "down "
-- Move t1 into reg2
atomic_code = atomic_code .. "begin dec " .. t1_to_reg2 .. "inc " .. reg2_to_t1 .. "end "
-- Restore old position
atomic_code = atomic_code .. t1_to_origin
elseif instruction[1] == "sub" then
local reg1 = tonumber(instruction[2]:sub(2)) + 8
local reg2 = tonumber(instruction[3]:sub(2)) + 8
local old_pos = memory_pointer
local move_to_operation = get_fix_move(old_pos, reg1)
local reg1_to_t1 = get_fix_move(reg1, 1)
local t1_to_reg1 = get_fix_move(1, reg1)
local reg1_to_reg2 = get_fix_move(reg1, reg2)
local reg2_to_t1 = get_fix_move(reg2, 1)
local t1_to_origin = get_fix_move(1, old_pos)
atomic_code = "## SUB " .. instruction[2] .. " to " .. instruction[3] .. " ##\n"
--move to reg1
atomic_code = atomic_code .. move_to_operation
-- move reg1 into t1
atomic_code = atomic_code .. "begin dec " .. reg1_to_t1 .. "inc " .. t1_to_reg1 .. "end "
-- move to t1
atomic_code = atomic_code .. reg1_to_t1
-- move t1 to reg1 and remove from reg2
atomic_code = atomic_code
.. "begin dec "
.. t1_to_reg1
.. "inc "
.. reg1_to_reg2
.. "dec "
.. reg2_to_t1
.. "end "
-- return to origin
atomic_code = atomic_code .. t1_to_origin
elseif instruction[1] == "loop" then
local reg = tonumber(instruction[2]:sub(2)) + 8
print("ERROR: Loops are not yet implemented!")
else
print("ERROR: The instruction " .. instruction[1] .. " is not a valid instruction!")
return content
end
return content .. atomic_code
end

View File

@ -0,0 +1,70 @@
# Complex Assembly Functions
## Memory sections
1. Register Area
2. Stack
3. Open Memory
## Navigation between sections
- Compiler logs current position
- Registers can be navigated relative to zero index
## Registers
$r0 := 0 (constant to be replaced in code)
$r1 .. $r31 := all purpose registers
$io := Input/Output register (translates to read / write instruction)
$t1 .. $t8:= Registers to be used by the assembler only
## Register cell map
| cell | register | description |
| ---- | -------- | ---------------------------------- |
| 0 | $t1 | Start of hidden registers |
| 8 | $r1 | All purpose programmable registers |
| 40 | $mem | Random access memory |
## Add function
1. Store current position
2. Move to reg 1
3. move reg 1 into t1, t2
4. move t2 into reg 1
5. move to t1
6. move t1 to reg 2
7. return to starting position
### add $10 $11:
Setup: >>>>>>>>>>>>>>>>>>++++++++++>+++++<<<<<<<<<<<<<<<<<<<
Move to reg1: >>>>>>>>>>>>>>>>>> (move to operation)
Move reg 1 into t1, t2: [-<<<<<<<<<<<<<<<<<<+>+>>>>>>>>>>>>>>>>>] (reg1 to t1)
Move t2 into reg 1: <<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<] (reg1 to t2)
Move to t1: <
Move t1 to reg 2: [->>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<] (t2 to reg2)
Optimization possible:
1. Moving reg1 to t1
2. Moving t1 to reg1 and reg2
3. Return to starting position
(Further optimization by checking the distances of reg1, reg2, t1 to avoid unnecessary steps)
### sub $5, $12
1. Move reg1 into t1
2. Move t1 into reg1, remove from reg2
while reg1:
reg1 --
t1 ++
### loop
Must store loop register and origin
Origin should be always the loop register inside loop
Old origin should be set on loopend

24
assembly/test.lua Normal file
View File

@ -0,0 +1,24 @@
require("complex_assembler")
require("atomic_assembler")
require("brainfuck_compiler")
local file = io.open("basic_logic.bf", "r")
local content = ""
if file ~= nil then
content = file:read("*all")
else
print("ERROR: Input file not found!")
end
local atomic = AssembleComplexCode(content)
local brainfuck = AssembleAtomicCode(atomic)
local machine_code = CompileBrainfuck(brainfuck, "logisim")
print(brainfuck)
print(machine_code)
local logisim_file = io.open("logisim.mem", "w")
logisim_file:write(machine_code)