Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393
Commits
4b874e41
Commit
4b874e41
authored
Jul 04, 2016
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding cocotb simulation control form the production code over sockets
parent
8bf77f19
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
306 additions
and
0 deletions
+306
-0
socket_command.py
cocotb/socket_command.py
+93
-0
x393coco_03.py
cocotb/x393coco_03.py
+213
-0
No files found.
cocotb/socket_command.py
0 → 100644
View file @
4b874e41
from
__future__
import
print_function
"""
# Copyright (C) 2016, Elphel.inc.
# Simulation code for cocotb simulation for x393 project
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
@author: Andrey Filippov
@copyright: 2016 Elphel, Inc.
@license: GPLv3.0+
@contact: andrey@elphel.coml
"""
import
json
import
socket
class
SocketCommand
():
command
=
None
arguments
=
None
def
__init__
(
self
,
command
=
None
,
arguments
=
None
):
# , debug=False):
self
.
command
=
command
self
.
arguments
=
arguments
def
getCommand
(
self
):
return
self
.
command
def
getArgs
(
self
):
return
self
.
arguments
def
getStart
(
self
):
return
self
.
command
==
"start"
def
getStop
(
self
):
return
self
.
command
==
"stop"
def
getWrite
(
self
):
return
self
.
arguments
if
self
.
command
==
"write"
else
None
def
getRead
(
self
):
return
self
.
arguments
if
self
.
command
==
"read"
else
None
def
setStart
(
self
):
self
.
command
=
"start"
def
setStop
(
self
):
self
.
command
=
"stop"
def
setWrite
(
self
,
arguments
):
self
.
command
=
"write"
self
.
arguments
=
arguments
def
setRead
(
self
,
arguments
):
self
.
command
=
"read"
self
.
arguments
=
arguments
def
toJSON
(
self
):
return
json
.
dumps
({
"cmd"
:
self
.
command
,
"args"
:
self
.
arguments
})
def
fromJSON
(
self
,
jstr
):
d
=
json
.
loads
(
jstr
)
try
:
self
.
command
=
d
[
'cmd'
]
except
:
self
.
command
=
None
try
:
self
.
arguments
=
d
[
'args'
]
except
:
self
.
arguments
=
None
class
x393Client
():
def
__init__
(
self
,
port
=
7777
,
host
=
'localhost'
):
self
.
PORT
=
port
self
.
HOST
=
host
# Symbolic name meaning all available interfaces
self
.
cmd
=
SocketCommand
()
def
communicate
(
self
,
snd_str
):
sock
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
sock
.
connect
((
self
.
HOST
,
self
.
PORT
))
sock
.
send
(
snd_str
)
reply
=
sock
.
recv
(
16384
)
# limit reply to 16K
sock
.
close
()
return
reply
def
start
(
self
):
self
.
cmd
.
setStart
()
print
(
"start->"
,
self
.
communicate
(
self
.
cmd
.
toJSON
()))
def
stop
(
self
):
self
.
cmd
.
setStop
()
print
(
"stop->"
,
self
.
communicate
(
self
.
cmd
.
toJSON
()))
def
write
(
self
,
address
,
data
):
self
.
cmd
.
setWrite
([
address
,
data
])
print
(
"write->"
,
self
.
communicate
(
self
.
cmd
.
toJSON
()))
def
read
(
self
,
address
):
self
.
cmd
.
setRead
(
address
)
rslt
=
self
.
communicate
(
self
.
cmd
.
toJSON
())
print
(
"read->"
,
rslt
)
return
json
.
loads
(
rslt
)
cocotb/x393coco_03.py
0 → 100644
View file @
4b874e41
from
__future__
import
print_function
"""
# Copyright (C) 2016, Elphel.inc.
# Simulation code for cocotb simulation for x393 project
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
@author: Andrey Filippov
@copyright: 2016 Elphel, Inc.
@license: GPLv3.0+
@contact: andrey@elphel.coml
"""
import
os
import
cocotb
import
socket
import
select
#import json
from
socket_command
import
SocketCommand
from
cocotb.triggers
import
Timer
from
x393buses
import
MAXIGPMaster
from
cocotb.drivers
import
BitDriver
from
cocotb.triggers
import
Timer
,
RisingEdge
,
ReadOnly
from
cocotb.result
import
ReturnValue
,
TestFailure
,
TestError
,
TestSuccess
import
logging
class
X393_cocotb
(
object
):
def
__init__
(
self
,
dut
,
port
,
host
):
# , debug=False):
"""
print("os.getenv('SIM_ROOT'",os.getenv('SIM_ROOT'))
print("os.getenv('COCOTB_DEBUG'",os.getenv('COCOTB_DEBUG'))
print("os.getenv('RANDOM_SEED'",os.getenv('RANDOM_SEED'))
print("os.getenv('MODULE'",os.getenv('MODULE'))
print("os.getenv('TESTCASE'",os.getenv('TESTCASE'))
print("os.getenv('COCOTB_ANSI_OUTPUT'",os.getenv('COCOTB_ANSI_OUTPUT'))
"""
debug
=
os
.
getenv
(
'COCOTB_DEBUG'
)
# None/1
self
.
cmd
=
SocketCommand
()
self
.
dut
=
dut
self
.
maxigp0
=
MAXIGPMaster
(
entity
=
dut
,
name
=
"dutm0"
,
clock
=
dut
.
dutm0_aclk
,
rdlag
=
0
,
blag
=
0
)
# self.clock = dut.dutm0_aclk
level
=
logging
.
DEBUG
if
debug
else
logging
.
WARNING
self
.
maxigp0
.
log
.
setLevel
(
level
)
#Initialize socket
self
.
PORT
=
port
self
.
HOST
=
host
# Symbolic name meaning all available interfaces
self
.
socket_conn
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
try
:
self
.
socket_conn
.
bind
((
self
.
HOST
,
self
.
PORT
))
self
.
dut
.
_log
.
debug
(
'Socket bind complete, HOST=
%
s, PORT=
%
d'
%
(
self
.
HOST
,
self
.
PORT
))
self
.
socket_conn
.
listen
(
1
)
# just a single request (may increase to 5 (backlog)
self
.
dut
.
_log
.
info
(
'Socket now listening to a single request on port
%
d: send command, receive response, close'
%
(
self
.
PORT
))
except
socket
.
error
as
msg
:
self
.
logErrorTerminate
(
'Bind failed. Error Code :
%
s Message
%
s'
%
(
str
(
msg
[
0
]),
msg
[
1
]))
def
logErrorTerminate
(
self
,
msg
):
self
.
dut
.
_log
.
error
(
msg
)
cocotb
.
regression
.
tear_down
()
raise
TestFailure
(
msg
)
@
cocotb
.
coroutine
def
receiveCommandFromSocket
(
self
):
line
=
None
try
:
self
.
soc_conn
,
soc_addr
=
self
.
socket_conn
.
accept
()
self
.
dut
.
_log
.
debug
(
"Connected with
%
s"
%
(
soc_addr
[
0
]
+
':'
+
str
(
soc_addr
[
1
])))
#Sending message to connected client
#self.soc_conn.send('Welcome to the server. Type something and hit enter\n') #send only takes string
line
=
self
.
soc_conn
.
recv
(
4096
)
# or make it unlimited?
self
.
dut
.
_log
.
info
(
"Received from socket:
%
s"
%
(
line
))
except
:
self
.
logErrorTerminate
(
"Socket seems to have died :-("
)
# return line
self
.
dut
.
_log
.
info
(
"1.Received from socket:
%
s"
%
(
line
))
yield
Timer
(
10000
)
# return line
# raise ReturnValue(line)
self
.
dut
.
_log
.
info
(
"2.Received from socket:
%
s"
%
(
line
))
yield
self
.
executeCommand
(
line
)
self
.
dut
.
_log
.
info
(
"3.Received from socket:
%
s"
%
(
line
))
# yield ReturnValue(line)
# return line
@
cocotb
.
coroutine
def
executeCommand
(
self
,
line
):
self
.
dut
.
_log
.
info
(
"1.executeCommand:
%
s"
%
(
line
))
if
not
line
:
raise
ReturnValue
(
None
)
self
.
dut
.
_log
.
info
(
"2.executeCommand:
%
s"
%
(
line
))
self
.
cmd
.
fromJSON
(
line
)
if
self
.
cmd
.
getStart
():
self
.
dut
.
_log
.
info
(
'Received START, waiting reset to be over'
)
yield
Timer
(
10000
)
while
self
.
dut
.
reset_out
.
value
.
get_binstr
()
!=
"1"
:
yield
Timer
(
10000
)
while
self
.
dut
.
reset_out
.
value
:
yield
Timer
(
10000
)
self
.
soc_conn
.
send
(
"'0'
\n
"
)
self
.
dut
.
_log
.
info
(
'Sent 0 to the socket'
)
elif
self
.
cmd
.
getStop
():
self
.
dut
.
_log
.
info
(
'Received STOP, closing...'
)
self
.
soc_conn
.
send
(
"'0'
\n
"
)
self
.
soc_conn
.
close
()
self
.
socket_conn
.
shutdown
(
socket
.
SHUT_RDWR
)
self
.
socket_conn
.
close
()
cocotb
.
regression
.
tear_down
()
raise
TestSuccess
(
'Terminating as received STOP command'
)
# raise ReturnValue(None)
def
convert_string
(
txt
):
number
=
0
for
c
in
txt
:
number
=
(
number
<<
8
)
+
ord
(
c
)
return
number
@
cocotb
.
coroutine
def
run_test
(
dut
,
port
=
7777
):
tb
=
X393_cocotb
(
dut
=
dut
,
host
=
""
,
port
=
7777
)
dut
.
_log
.
info
(
"Waiting for commnad on socket port
%
s"
%
(
port
))
while
True
:
try
:
rslt
=
yield
tb
.
receiveCommandFromSocket
()
dut
.
_log
.
info
(
"command_line =
%
s"
%
(
str
(
rslt
)))
except
ReturnValue
as
rv
:
command_line
=
rv
.
retval
;
dut
.
_log
.
info
(
"rv =
%
s"
%
(
str
(
rv
)))
dut
.
_log
.
info
(
"command_line =
%
s"
%
(
str
(
command_line
)))
# try:
# rslt = yield tb.executeCommand(command_line)
# except:
# break;
tb
.
socket_conn
.
close
()
cocotb
.
regression
.
tear_down
()
def
run_test_0
(
dut
):
tb
=
X393_cocotb
(
dut
=
dut
,
host
=
""
,
port
=
7777
)
# tb.logErrorTerminate('Test error terminate')
yield
Timer
(
10000
)
while
dut
.
reset_out
.
value
.
get_binstr
()
!=
"1"
:
yield
Timer
(
10000
)
while
dut
.
reset_out
.
value
:
yield
Timer
(
10000
)
# dut.TEST_TITLE.buff = "WRITE"
dut
.
TEST_TITLE
=
convert_string
(
"WRITE"
)
val
=
yield
tb
.
maxigp0
.
axi_write
(
address
=
0x1234
,
value
=
[
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
0
],
byte_enable
=
None
,
id
=
0
,
dsize
=
2
,
burst
=
1
,
address_latency
=
0
,
data_latency
=
0
)
# dut.TEST_TITLE.buff = "---"
dut
.
TEST_TITLE
=
0
dut
.
_log
.
info
(
"axi_write returned => "
+
str
(
val
))
# yield Timer(1000)
print
(
"*******************************************"
)
yield
Timer
(
11000
)
dut
.
TEST_TITLE
=
convert_string
(
"WRITE1"
)
val
=
yield
tb
.
maxigp0
.
axi_write
(
address
=
0x5678
,
value
=
[
1
,
2
,
3
,
4
],
byte_enable
=
None
,
id
=
0
,
dsize
=
2
,
burst
=
1
,
address_latency
=
0
,
data_latency
=
0
)
# dut.TEST_TITLE.buff = "---"
dut
.
TEST_TITLE
=
0
dut
.
_log
.
info
(
"axi_write returned => "
+
str
(
val
))
# yield Timer(1000)
print
(
"*******************************************"
)
yield
Timer
(
10000
)
# dval = yield tb.maxigp0.axi_read(0x1234, 0, 4, 2, 0, 0 )
# dut.TEST_TITLE.buff = "READ"
dut
.
TEST_TITLE
<=
convert_string
(
"READ"
)
dval
=
yield
tb
.
maxigp0
.
axi_read
(
address
=
0x1234
,
id
=
0
,
dlen
=
4
,
dsize
=
2
,
address_latency
=
0
,
data_latency
=
0
)
dut
.
_log
.
info
(
"axi_read returned => "
+
str
(
dval
))
# dut.TEST_TITLE.buff = "---"
dut
.
TEST_TITLE
<=
0
yield
Timer
(
100000
)
print
(
"*******************************************"
)
cocotb
.
regression
.
tear_down
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment