Files
Gameboy_MiSTer/sim/tests/vsim_comm.lua
2020-12-15 15:23:28 +01:00

418 lines
9.2 KiB
Lua

function string:split(sep)
local sep, fields = sep or ":", {}
local pattern = string.format("([^%s]+)", sep)
self:gsub(pattern, function(c) fields[#fields+1] = c end)
return fields
end
function conv_neg(x)
if (x < 0) then
return (2147483647 + (2147483649 - ((x * (-1)) )))
else
return x
end
end
function conv_to_neg(x)
if (x > 2147483647) then
return x - (2* 2147483648)
else
return x
end
end
function binary_and(a,b)
local r = 0
local neg = 1
if (a < 0) then
a = a * (-1)
neg = neg * (-1)
end
if (b < 0) then
b = b * (-1)
neg = neg * (-1)
end
for i = 31, 0, -1 do
local x = 2^i
if (a >= x and b>=x) then
r = r + 2^i
end
if (a >= x) then
a = a - x
end
if (b >= x) then
b = b - x
end
end
return r * neg
end
function binary_or(a,b)
local r = 0
local neg = 1
if (a < 0) then
a = a * (-1)
neg = neg * (-1)
end
if (b < 0) then
b = b * (-1)
neg = neg * (-1)
end
for i = 31, 0, -1 do
local x = 2^i
if (a >= x or b>=x) then
r = r + 2^i
end
if (a >= x) then
a = a - x
end
if (b >= x) then
b = b - x
end
end
return r * neg
end
--------------
-- file access
--------------
inputfile = "../input.txt"
outputfile = "../output.txt"
blockwritesize = 128
wait_on_writeblock = true
function write_one(command)
local file = nil
while (file == nil) do
file=io.open(inputfile,"a+")
end
io.output(file)
io.write(command)
io.write("\n")
io.close(file)
end
function read_one(command)
local read_line = ""
command = string.sub(command, 1, #command - 1)
--print("#command: "..#command)
if (endpointer > 1000) then
endpointer = endpointer - 1000
else
endpointer = 0
end
while read_line ~= command do
local file = nil
while (file == nil) do
file=io.open(outputfile,"r")
end
file:seek("set", endpointer)
local line = file:read()
while (line ~= nil) do
local buf_line = line
local ix = #command + 1
while ix < #buf_line do
if (string.sub(buf_line,ix,ix) == "#") then
break
end
ix = ix + 1
end
result = string.sub(buf_line,ix + 2,#buf_line - 1)
buf_line = string.sub(buf_line,0,ix - 2)
--print("########")
--print(line)
--print(command)
--print(buf_line)
--print("Result:"..result)
if (buf_line == command) then
read_line = buf_line
break;
end
line = file:read()
end
new_endpointer = file:seek("end")
io.close(file)
end
endpointer = new_endpointer
return result
end
-------------------
-- connect commands
-------------------
function reg_get_block_connection(reg, index, size)
command_nr = command_nr + 1
if (index == null) then index = 0 end
block = {}
local readindex = 0
local dataleft = size
while (dataleft > 0) do
local blocksize = math.min(dataleft, 128)
command = "get # "..command_nr.." # "..process_id.." # ".."1".." # "..blocksize.." # "..(reg[1] + index).."&"
write_one(command)
values = read_one(command)
blockraw = values:split("#")
for i = 1, blocksize do
block[readindex] = tonumber(blockraw[i])
readindex = readindex + 1
end
dataleft = dataleft - blocksize
index = index + blocksize
end
return block
end
function reg_get_connection(reg, index)
block = reg_get_block_connection(reg, index, 1)
return block[0]
end
function reg_set_block_connection(values, reg, index)
if (index == null) then index = 0 end
command_nr = command_nr + 1
local length = (#values + 1)
command = "set # "..command_nr.." # "..process_id.." # ".."1".." # "..math.min(blockwritesize, length).." # "..(reg[1] + index)
local writecount = 0
for i = 0, #values do
value = conv_to_neg(values[i])
command = command.." # "..value
writecount = writecount + 1
if (writecount == blockwritesize) then
command = command.."&"
write_one(command)
if (wait_on_writeblock) then
read_one(command)
end
writecount = 0
index = index + blockwritesize
command_nr = command_nr + 1
length = length - blockwritesize
command = "set # "..command_nr.." # "..process_id.." # ".."1".." # "..math.min(blockwritesize, length).." # "..(reg[1] + index)
end
end
if (length > 0) then
command = command.."&"
write_one(command)
if (wait_on_writeblock) then
read_one(command)
end
end
end
function reg_set_connection(value, reg, index)
values = {}
values[0] = value
reg_set_block_connection(values, reg, index)
end
-----------
-- commands
-----------
function reg_filter(reg, value)
filter = 0
for i = reg[3], reg[2] do
filter = filter + 2^i;
end
value = conv_neg(value)
value = binary_and(value,filter);
value = value / (2 ^ reg[3]);
return value
end
function reg_get(reg, index)
value = reg_get_connection(reg, index)
value = reg_filter(reg, value)
return value
end
function reg_get_block(reg, index, size)
block = reg_get_block_connection(reg, index, size)
for i = 0, size - 1 do
value = block[i]
filter = 0
for i = reg[3], reg[2] do
filter = filter + 2^i;
end
value = conv_neg(value)
value = binary_and(value,filter);
value = value / (2 ^ reg[3]);
block[i] = value
end
return block
end
function reg_set_block(block, reg, index)
reg_set_block_connection(block, reg, index)
end
function reg_set(value, reg, index)
if (index == null) then index = 0 end
if (value < 100) then
--print ("Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] => "..value)
else
--print ("Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] => 0x"..string.format("%X", value))
end
-- find out if parameter is the only one in this register
local singlereg = true
local fullname = reg[6]
local sectionname = fullname:split(".")[1]
local secttable = _G[sectionname]
for name, register in pairs(secttable) do
if (register[1] == reg[1]) then
if (register[6] ~= reg[6]) then
singlereg = false
break
end
end
end
oldval = 0
if (singlereg == false) then
oldval = reg_get_connection(reg, index)
--print ("oldval= "..oldval.." at "..(reg[1]+index))
filter = 0
for i = 0, reg[3] - 1 do
filter = filter + 2^i;
end
for i = reg[2] + 1, 31 do
filter = filter + 2^i;
end
oldval = binary_and(oldval,filter);
--print ("oldval filtered= "..oldval.." at "..(reg[1]+index).." with filter "..filter)
end
value = value * (2 ^ reg[3])
value = binary_or(value, oldval);
reg_set_connection(value, reg, index)
end
function compare_reg(target, reg, index)
if (index == null) then index = 0 end
value = reg_get(reg, index)
if (value == target) then
if (value < 100 and target < 100) then
print (reg[6].." -> Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] = "..value.." - OK")
else
print (reg[6].." -> Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] = 0x"..string.format("%X", value).." - OK")
end
return true
else
testerrorcount = testerrorcount + 1
if (value < 100 and target < 100) then
print (reg[6].." -> Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] = "..value.." | should be = "..target.." - ERROR")
else
print (reg[6].." -> Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] = 0x"..string.format("%X", tonumber(value)).." | should be = 0x"..string.format("%X", tonumber(target)).." - ERROR")
end
return false;
end
end
function reg_set_file(filename, baseaddress, index, endian)
if (index == null) then index = 0 end
if (endian == null) then endian = 0 end
command_nr = command_nr + 1
command = "fil # "..command_nr.." # "..process_id.." # "..endian.." # "..(baseaddress + index).." # "..filename
command = command.."&"
write_one(command)
if (wait_on_writeblock) then
read_one(command)
end
end
function wait_ns(waittime)
command_nr = command_nr + 1
command = "wtn # "..command_nr.." # "..process_id.." # "..waittime.."&"
write_one(command)
read_one(command)
end
function brk()
command_nr = command_nr + 1
command = "brk&"
write_one(command)
end
function sleep(n) -- seconds
local t0 = os.clock()
while os.clock() - t0 <= n do end
end
----------
-- init
----------
seed = os.time() + os.clock() * 1000
math.randomseed(seed)
process_id = math.random(2147483647)
process_id = math.random(2147483647)
process_id = math.random(2147483647)
process_id = math.random(2147483647)
process_id = math.random(2147483647)
endpointer = 0
command_nr = 0