mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
etherbone: clean up ohwr dissector, Python model checked against it
This commit is contained in:
parent
5728f61f3a
commit
02bfc0a5a8
3 changed files with 320 additions and 101 deletions
260
liteeth/core/etherbone/dissector/bit.lua
Normal file
260
liteeth/core/etherbone/dissector/bit.lua
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
--[[---------------
|
||||||
|
LuaBit v0.4
|
||||||
|
-------------------
|
||||||
|
a bitwise operation lib for lua.
|
||||||
|
|
||||||
|
http://luaforge.net/projects/bit/
|
||||||
|
|
||||||
|
How to use:
|
||||||
|
-------------------
|
||||||
|
bit.bnot(n) -- bitwise not (~n)
|
||||||
|
bit.band(m, n) -- bitwise and (m & n)
|
||||||
|
bit.bor(m, n) -- bitwise or (m | n)
|
||||||
|
bit.bxor(m, n) -- bitwise xor (m ^ n)
|
||||||
|
bit.brshift(n, bits) -- right shift (n >> bits)
|
||||||
|
bit.blshift(n, bits) -- left shift (n << bits)
|
||||||
|
bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>)
|
||||||
|
|
||||||
|
Please note that bit.brshift and bit.blshift only support number within
|
||||||
|
32 bits.
|
||||||
|
|
||||||
|
2 utility functions are provided too:
|
||||||
|
bit.tobits(n) -- convert n into a bit table(which is a 1/0 sequence)
|
||||||
|
-- high bits first
|
||||||
|
bit.tonumb(bit_tbl) -- convert a bit table into a number
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Under the MIT license.
|
||||||
|
|
||||||
|
copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
|
||||||
|
--]]---------------
|
||||||
|
|
||||||
|
do
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- bit lib implementions
|
||||||
|
|
||||||
|
local function check_int(n)
|
||||||
|
-- checking not float
|
||||||
|
if(n - math.floor(n) > 0) then
|
||||||
|
error("trying to use bitwise operation on non-integer!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function to_bits(n)
|
||||||
|
check_int(n)
|
||||||
|
if(n < 0) then
|
||||||
|
-- negative
|
||||||
|
return to_bits(bit.bnot(math.abs(n)) + 1)
|
||||||
|
end
|
||||||
|
-- to bits table
|
||||||
|
local tbl = {}
|
||||||
|
local cnt = 1
|
||||||
|
while (n > 0) do
|
||||||
|
local last = math.mod(n,2)
|
||||||
|
if(last == 1) then
|
||||||
|
tbl[cnt] = 1
|
||||||
|
else
|
||||||
|
tbl[cnt] = 0
|
||||||
|
end
|
||||||
|
n = (n-last)/2
|
||||||
|
cnt = cnt + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return tbl
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tbl_to_number(tbl)
|
||||||
|
local n = table.getn(tbl)
|
||||||
|
|
||||||
|
local rslt = 0
|
||||||
|
local power = 1
|
||||||
|
for i = 1, n do
|
||||||
|
rslt = rslt + tbl[i]*power
|
||||||
|
power = power*2
|
||||||
|
end
|
||||||
|
|
||||||
|
return rslt
|
||||||
|
end
|
||||||
|
|
||||||
|
local function expand(tbl_m, tbl_n)
|
||||||
|
local big = {}
|
||||||
|
local small = {}
|
||||||
|
if(table.getn(tbl_m) > table.getn(tbl_n)) then
|
||||||
|
big = tbl_m
|
||||||
|
small = tbl_n
|
||||||
|
else
|
||||||
|
big = tbl_n
|
||||||
|
small = tbl_m
|
||||||
|
end
|
||||||
|
-- expand small
|
||||||
|
for i = table.getn(small) + 1, table.getn(big) do
|
||||||
|
small[i] = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bit_or(m, n)
|
||||||
|
local tbl_m = to_bits(m)
|
||||||
|
local tbl_n = to_bits(n)
|
||||||
|
expand(tbl_m, tbl_n)
|
||||||
|
|
||||||
|
local tbl = {}
|
||||||
|
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
|
||||||
|
for i = 1, rslt do
|
||||||
|
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
|
||||||
|
tbl[i] = 0
|
||||||
|
else
|
||||||
|
tbl[i] = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return tbl_to_number(tbl)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bit_and(m, n)
|
||||||
|
local tbl_m = to_bits(m)
|
||||||
|
local tbl_n = to_bits(n)
|
||||||
|
expand(tbl_m, tbl_n)
|
||||||
|
|
||||||
|
local tbl = {}
|
||||||
|
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
|
||||||
|
for i = 1, rslt do
|
||||||
|
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
|
||||||
|
tbl[i] = 0
|
||||||
|
else
|
||||||
|
tbl[i] = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return tbl_to_number(tbl)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bit_not(n)
|
||||||
|
|
||||||
|
local tbl = to_bits(n)
|
||||||
|
local size = math.max(table.getn(tbl), 32)
|
||||||
|
for i = 1, size do
|
||||||
|
if(tbl[i] == 1) then
|
||||||
|
tbl[i] = 0
|
||||||
|
else
|
||||||
|
tbl[i] = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return tbl_to_number(tbl)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bit_xor(m, n)
|
||||||
|
local tbl_m = to_bits(m)
|
||||||
|
local tbl_n = to_bits(n)
|
||||||
|
expand(tbl_m, tbl_n)
|
||||||
|
|
||||||
|
local tbl = {}
|
||||||
|
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
|
||||||
|
for i = 1, rslt do
|
||||||
|
if(tbl_m[i] ~= tbl_n[i]) then
|
||||||
|
tbl[i] = 1
|
||||||
|
else
|
||||||
|
tbl[i] = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--table.foreach(tbl, print)
|
||||||
|
|
||||||
|
return tbl_to_number(tbl)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bit_rshift(n, bits)
|
||||||
|
check_int(n)
|
||||||
|
|
||||||
|
local high_bit = 0
|
||||||
|
if(n < 0) then
|
||||||
|
-- negative
|
||||||
|
n = bit_not(math.abs(n)) + 1
|
||||||
|
high_bit = 2147483648 -- 0x80000000
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=1, bits do
|
||||||
|
n = n/2
|
||||||
|
n = bit_or(math.floor(n), high_bit)
|
||||||
|
end
|
||||||
|
return math.floor(n)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- logic rightshift assures zero filling shift
|
||||||
|
local function bit_logic_rshift(n, bits)
|
||||||
|
check_int(n)
|
||||||
|
if(n < 0) then
|
||||||
|
-- negative
|
||||||
|
n = bit_not(math.abs(n)) + 1
|
||||||
|
end
|
||||||
|
for i=1, bits do
|
||||||
|
n = n/2
|
||||||
|
end
|
||||||
|
return math.floor(n)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bit_lshift(n, bits)
|
||||||
|
check_int(n)
|
||||||
|
|
||||||
|
if(n < 0) then
|
||||||
|
-- negative
|
||||||
|
n = bit_not(math.abs(n)) + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=1, bits do
|
||||||
|
n = n*2
|
||||||
|
end
|
||||||
|
return bit_and(n, 4294967295) -- 0xFFFFFFFF
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bit_xor2(m, n)
|
||||||
|
local rhs = bit_or(bit_not(m), bit_not(n))
|
||||||
|
local lhs = bit_or(m, n)
|
||||||
|
local rslt = bit_and(lhs, rhs)
|
||||||
|
return rslt
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- bit lib interface
|
||||||
|
|
||||||
|
bit = {
|
||||||
|
-- bit operations
|
||||||
|
bnot = bit_not,
|
||||||
|
band = bit_and,
|
||||||
|
bor = bit_or,
|
||||||
|
bxor = bit_xor,
|
||||||
|
brshift = bit_rshift,
|
||||||
|
blshift = bit_lshift,
|
||||||
|
bxor2 = bit_xor2,
|
||||||
|
blogic_rshift = bit_logic_rshift,
|
||||||
|
|
||||||
|
-- utility func
|
||||||
|
tobits = to_bits,
|
||||||
|
tonumb = tbl_to_number,
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
for i = 1, 100 do
|
||||||
|
for j = 1, 100 do
|
||||||
|
if(bit.bxor(i, j) ~= bit.bxor2(i, j)) then
|
||||||
|
error("bit.xor failed.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
-- value-string maps for the protocol fields
|
-- Etherbone Dissector
|
||||||
|
-- Copyright 2013 OHWR.org
|
||||||
|
-- Copyright 2015 EnjoyDigital (global clean up)
|
||||||
|
|
||||||
local bit = require("bit")
|
local bit = require("bit")
|
||||||
|
|
||||||
local VALS_BAR = {[0x11] = "Whiskey", [0x12] = "Rum", [0x13] =
|
|
||||||
"Vodka", [0x14] = "Gin"}
|
|
||||||
local VALS_BOOL = {[0] = "False", [1] = "True"}
|
local VALS_BOOL = {[0] = "False", [1] = "True"}
|
||||||
local VALS_RES = {[0] = "not set", [1] = "set, bad data?"}
|
local VALS_RES = {[0] = "not set", [1] = "set, bad data?"}
|
||||||
local VALS_SIZE = {
|
local VALS_SIZE = {
|
||||||
|
@ -25,7 +25,6 @@ local VALS_SIZE = {
|
||||||
[0x0F] = "64,32,16,8 bit",
|
[0x0F] = "64,32,16,8 bit",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Returns HEX representation of num
|
|
||||||
function num2hex(num)
|
function num2hex(num)
|
||||||
local hexstr = '0123456789abcdef'
|
local hexstr = '0123456789abcdef'
|
||||||
local s = ''
|
local s = ''
|
||||||
|
@ -46,11 +45,10 @@ function max(a, b)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Declare protocol
|
-- declare protocol
|
||||||
proto_eb = Proto("eb", "Etherbone")
|
proto_eb = Proto("eb", "Etherbone")
|
||||||
|
|
||||||
|
-- declare fields
|
||||||
-- Declare its fields
|
|
||||||
local eb = proto_eb.fields
|
local eb = proto_eb.fields
|
||||||
eb.hdr = ProtoField.uint32("eb.hdr", "Header", base.HEX)
|
eb.hdr = ProtoField.uint32("eb.hdr", "Header", base.HEX)
|
||||||
eb.rec = ProtoField.bytes("eb.rec", "Record ", base.HEX)
|
eb.rec = ProtoField.bytes("eb.rec", "Record ", base.HEX)
|
||||||
|
@ -97,28 +95,21 @@ eb.rec_rddata16 = ProtoField.uint16("eb.rec.rddata16", "Address16 ", base.H
|
||||||
eb.rec_rddata32 = ProtoField.uint32("eb.rec.rddata32", "Address32 ", base.HEX)
|
eb.rec_rddata32 = ProtoField.uint32("eb.rec.rddata32", "Address32 ", base.HEX)
|
||||||
eb.rec_rddata64 = ProtoField.uint64("eb.rec.rddata64", "Address64 ", base.HEX)
|
eb.rec_rddata64 = ProtoField.uint64("eb.rec.rddata64", "Address64 ", base.HEX)
|
||||||
|
|
||||||
-- Define the dissector
|
-- define the dissector
|
||||||
function proto_eb.dissector(buf, pinfo, tree)
|
function proto_eb.dissector(buf, pinfo, tree)
|
||||||
|
if (buf:len() < 4) then
|
||||||
-- min length, 4 for eb hdr with probe
|
return 0 -- too short, go to default protocol
|
||||||
local EXPECTED_LENGTH = 4
|
|
||||||
|
|
||||||
|
|
||||||
if (buf:len() < EXPECTED_LENGTH) then
|
|
||||||
-- not ours, let it go to default Data dissector
|
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local mylen = buf:len()
|
local mylen = buf:len()
|
||||||
pinfo.cols.protocol = "eb"
|
pinfo.cols.protocol = "eb"
|
||||||
|
|
||||||
-- add our packet to the tree root...we'll add fields to its subtree
|
-- add packet to the tree root, fields will be added to subtree
|
||||||
local t = tree:add( proto_eb, buf(0, mylen) )
|
local t = tree:add( proto_eb, buf(0, mylen) )
|
||||||
local t_hdr = t:add( eb.hdr, buf(0,4) ) -- hdr
|
local t_hdr = t:add( eb.hdr, buf(0,4) )
|
||||||
|
|
||||||
local magic = num2hex(tonumber(buf(0,2):uint()))
|
local magic = num2hex(tonumber(buf(0,2):uint()))
|
||||||
if(magic == "4e6f") then -- is this a valid etherbone packet ?
|
if(magic == "4e6f") then
|
||||||
|
|
||||||
t_hdr:add( eb.hdr_magic, buf(0,2)) -- magic
|
t_hdr:add( eb.hdr_magic, buf(0,2)) -- magic
|
||||||
t_hdr:add( eb.hdr_ver, buf(2,2)) -- version
|
t_hdr:add( eb.hdr_ver, buf(2,2)) -- version
|
||||||
|
@ -139,11 +130,6 @@ function proto_eb.dissector(buf, pinfo, tree)
|
||||||
local record_alignment = max(alignment, 4)
|
local record_alignment = max(alignment, 4)
|
||||||
local offset = max(alignment, 4)
|
local offset = max(alignment, 4)
|
||||||
|
|
||||||
--local t_foo = t:add( "Addr "..tostring(addr_width), buf(4,4))
|
|
||||||
--local t_foo = t:add( "Data "..tostring(data_width), buf(4,4))
|
|
||||||
--local t_foo = t:add( "Value Alignment "..tostring(alignment), buf(4,4))
|
|
||||||
--local t_foo = t:add( "Record Alignment "..tostring(record_alignment), buf(4,4))
|
|
||||||
|
|
||||||
local recordcnt = 0
|
local recordcnt = 0
|
||||||
while (offset < buf:len()) do
|
while (offset < buf:len()) do
|
||||||
local wr = tonumber(buf(offset+2,1):uint())
|
local wr = tonumber(buf(offset+2,1):uint())
|
||||||
|
@ -158,11 +144,6 @@ function proto_eb.dissector(buf, pinfo, tree)
|
||||||
wradr = 1
|
wradr = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- t_rec = t:add(wr)
|
|
||||||
-- t_rec = t:add(rd)
|
|
||||||
-- t_rec = t:add(offset)
|
|
||||||
-- t_rec = t:add((1+rd+wr+rdadr+wradr)*4)
|
|
||||||
if((wr == 0) and (rd == 0)) then
|
if((wr == 0) and (rd == 0)) then
|
||||||
offset = offset + record_alignment
|
offset = offset + record_alignment
|
||||||
else
|
else
|
||||||
|
@ -235,30 +216,8 @@ function proto_eb.dissector(buf, pinfo, tree)
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- local offset = 4
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- while offset <= mylen do
|
|
||||||
|
|
||||||
|
|
||||||
-- local rec = buf(offset,4)
|
|
||||||
|
|
||||||
-- if (buf:len() < EXPECTED_LENGTH + 4) then
|
|
||||||
--not ours, let it go to default Data dissector
|
|
||||||
-- return 0
|
|
||||||
-- end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Register eb protocol on UDP port 22222
|
-- register eb protocol on UDP port 20000
|
||||||
local tab = DissectorTable.get("udp.port")
|
local tab = DissectorTable.get("udp.port")
|
||||||
tab:add(60368, proto_eb)
|
tab:add(20000, proto_eb)
|
||||||
tab:add(8183, proto_eb)
|
|
|
@ -262,7 +262,7 @@ if __name__ == "__main__":
|
||||||
# Send packet over UDP to check against Wireshark dissector
|
# Send packet over UDP to check against Wireshark dissector
|
||||||
import socket
|
import socket
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
sock.sendto(bytes(packet), ("192.168.1.1", 60368))
|
sock.sendto(bytes(packet), ("192.168.1.1", 20000))
|
||||||
|
|
||||||
packet = EtherbonePacket(packet)
|
packet = EtherbonePacket(packet)
|
||||||
packet.decode()
|
packet.decode()
|
||||||
|
|
Loading…
Reference in a new issue