Skip to content
Snippets Groups Projects
Commit 00fabc77 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Moved OneClick documents from $UNB to $RADIOHDL.

Added the trails Python scripts made by Daniel van der Schuur (DS) and Harm Jan Pepping (HJP).
Added oneclick_prestudy_readme.txt to keep track of some prestudy meetings and discussions.
parent b26b377a
No related branches found
No related tags found
No related merge requests found
import multiprocessing
NOF_PARALLEL_STREAMS = range(1000)
def sink(inst_number, p_snk,p_src):
p_src.close() # Close this local connection to source end of the pipe
my_list = []
while True:
try:
item = p_snk.recv()
#print inst_number, item
except EOFError:
break
my_list.append(item**3)
def source(p_snk,p_src):
p_snk.close() # Close this local connection to the sink end of the pipe
for item in xrange(2000000):
p_src.send(item)
p_src.close()
if __name__ == '__main__':
pipes = []
sinks = []
sources = []
for i in NOF_PARALLEL_STREAMS:
# Create pipe and return connections to the source and sink sides of the pipe
pipes.append( multiprocessing.Pipe(duplex=False) )
# Separate sink process
sinks.append( multiprocessing.Process(target=sink, args=(i, pipes[i][0], pipes[i][1])) )
sinks[i].start()
# Separate source process
sources.append( multiprocessing.Process(target=source, args=(pipes[i][0], pipes[i][1])) )
sources[i].start()
File added
File added
File added
File added
File added
###############################################################################
#
# Copyright (C) 2012
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
# 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/>.
#
###############################################################################
"""
One-Click prototype model "X"
Remark: This example shows how a simple sysmtem of a block generator,
a multiplexer and a databuffer can be modelled using threads
with queues.
"""
###############################################################################
# System imports
import threading
import Queue
import time
###############################################################################
# Functions
class base_component(object):
def __init__(self, name, nof_inputs=0, nof_outputs=0, packetsize=10 ):
self.name = name
self.nof_inputs = nof_inputs
self.nof_outputs = nof_outputs
self.packetsize = packetsize
self.in_q = []
for i in range(nof_inputs):
self.in_q.append(Queue.Queue(packetsize))
self.out_q = []
print 'Instantiating', self.name
#'>' operator: Connect
def __gt__(self, other):
return self.__connect__(other)
def __connect__(self, other):
if hasattr(other, 'in_q'):
for j in xrange(self.nof_outputs):
self.out_q.append(other.in_q[j])
print 'connecting', self.name, 'to', other.name
return other
else:
print 'Error: downstream component', other.name, 'does not have snk'
def run(self):
return None
# Components inheriting the base component class
class blockGen(threading.Thread, base_component):
def __init__(self, nof_outputs=1, data=[]):
threading.Thread.__init__(self)
base_component.__init__(self, 'blockGen', 0, nof_outputs, len(data[0][0]) )
self.data = data
def run(self):
for i in xrange(len(self.data)):
for j in xrange(self.nof_outputs):
self.out_q[j].put(self.data[i][j])
print "Sending packet " + str(i) + " on stream " + str(j)
# time.sleep(1)
class dp_mux(threading.Thread, base_component):
def __init__(self, nof_inputs=2, nof_outputs=1, packetsize=10 ):
threading.Thread.__init__(self)
base_component.__init__(self, 'dp_mux', nof_inputs, nof_outputs, packetsize)
def run(self):
while True:
data = []
for i in xrange(self.nof_inputs):
data.append(self.in_q[i].get())
for j in xrange(self.nof_inputs):
self.out_q[0].put(data[j])
class dataBuffer(threading.Thread, base_component):
def __init__(self, nof_inputs=1, nof_outputs=0, packetsize=10, nof_packets=12 ):
threading.Thread.__init__(self)
base_component.__init__(self, 'dataBuffer', nof_inputs, nof_outputs, packetsize)
self.nof_packets = nof_packets
def run(self):
data = []
for j in xrange(self.nof_packets):
for i in xrange(self.nof_inputs):
data.append(self.in_q[i].get())
for i in data:
print i
# Some definitions
packetsize = 10
bg_nof_outputs = 2
nof_transm_packets = 12
nof_receiv_packets = 24
# Create data for the block generator
#
# bg_data=[h][i][j]
# h = [0:nof_transm_packets-1]
# i = [0:nof_outputs-1]
# j = [0:packetsize-1]
#
# The size of bg_data determines the various paramters of the model.
bg_data = []
for h in xrange(nof_transm_packets):
packets = []
for i in xrange(bg_nof_outputs):
packet = []
for j in xrange(packetsize):
packet.append(j+i*packetsize+h*bg_nof_outputs*packetsize)
packets.append(packet)
bg_data.append(packets)
# Instantiate the components for the system
bg = blockGen(bg_nof_outputs, bg_data)
mux = dp_mux(bg_nof_outputs, 1, packetsize)
db = dataBuffer(1, 0 , packetsize, nof_receiv_packets)
# Connect the components
bg > mux > db
# Start the threads
bg.start()
mux.start()
db.start()
# Our base class
class module(object):
def __init__(self, name):
self.name = name
print 'Instantiating', self.name
print '. (paste instance + signal declarations in VHDL file)'
#'>' operator: Connect
def __gt__(self, other):
return self.__connect__(other)
def __connect__(self, other):
if hasattr(other, 'snk'):
other.snk = self.src
other.func()
print 'connecting', self.name, 'to', other.name
print '. (paste signal assignments in VHDL file)'
return other
else:
print 'Error: downstream component', other.name, 'does not have snk'
def func(self):
return None
# Components inheriting our base class
class dp_src(module):
def __init__(self):
module.__init__(self, 'dp_src')
# Call func on init as this component does not require snk input to produce src
self.func()
def func(self): # Declare that this module has a src and provide the func that models it
self.src = [0,1,2,3,4,5,6]
class dp_incr(module):
def __init__(self):
module.__init__(self, 'dp_incr')
self.snk = [] # Declare that this module has a snk
def func(self): # Declare that this module has a src and the func that models it
src = []
for word in self.snk:
src.append(word+10)
self.src = src
class dp_snk(module):
def __init__(self):
module.__init__(self, 'dp_snk')
self.snk = [] # Declare that this module has a snk
def func(self):
self.ram = self.snk
# Basic concept for a top-level Python design description
# =============================================================
# Instantiatiations (paste instance + signal declarations in VHDL file)
a=dp_src()
b=dp_incr()
c=dp_snk()
print ''
# system flow desciption (for functional modeling and pasting signal assignments in VHDL file)
# . The '>' operator is overloaded and calls module.connect().
a>b>c
print ''
# Simple example of functional modeling
print 'a.src:', a.src # src output is defined by a.func()
print 'b.snk:', b.snk
print 'b.src:', b.src # src output is defined by b.func()
print 'c.snk:', c.snk
This file keeps some historical notes on the OneClick prestudy results.
1) Initial concept, 10 feb 2014
- ASTRON_SP_056_One_Click_Design_Flow_Specification, HJP, DS, EK
- one_click_concept.py, DS
The one_click_concept.py script defines some basic component classes and
starts instantiating and connecting at line 59 while printing what it's doing.
If you like, you could add a second (and 3rd, 4th, ..) dp_incr instance 'b2'
and connect it between 'b' and 'c'. The printed output changes accordingly.
It's minimal, but hopefully illustrates the concept.
2) Data driven or RTL accurate, telecon with SA, 15 may 2014
a)SA are doing trials with MyHDL. They want designers to have access to the RTL
without having to know VHDL, because this makes the development feasible
for a broad community of engineers like they have now with Matlab/Simulink,
and not only to digital engineers. RTL access in Python is what MyHDL
provides. MyHDL simulates HDL at the RTL level, i.e. event driven with clocks.
The parallel simulation is achieved using sensitivity lists, similar as in
VHDL.
b) Astron wants to model the DSP at the data level, so without the clock. The
parallel simulation is not achieved by a sensitivity list and functions that
are processed each time an input changes, but instead a function is only
processed when it has sufficient data to calculate its next new output. Hence
input data is only processed once. The functions may be mapped on software
processes, threads or in a sequential loop. The next investigations focus on
using software processes or threads, and on using pipes or queues.
c) MyHDL could be supported in the Astron scheme by treating the MyHDL
components as just another source for creating RTL components. Default at
Astron we develop our RTL components in VHDL, but one may also start coding
in MyHDL and then use the toVHDL() function to convert it to an VHDL
component. The advantage of a MyHDL component is that the RTL description
in Python can also serve as behavioral model in Python by simply adding
an local clock source (assuming that the RTL description uses the standard
MM and ST interfaces). For the VHDL components we manually need to create
a model in Python. However this model is typically quite simple.
3) Explorations, 3 june 2014
- 7_stream_simplex_2_comp_parallel.py
Show using software processes and pipes to model components. With 20 processes
on the 12 core CPU of dop233 this runs much faster then on a quad core CPU.
The maximum number of processes seems to be about 800. The processes could
even run on different machines via a network, this may provide quite
interesting possibilities for modelling very large systems.
- multithreads.py, HJP
Show using threads and queues to model components. The example models the
chain of BG > MUX > DB. Threads provide parallelism however in Python they
all run in one process, so on one core.
- Remarks:
a modelling fanin is not needed, because this does not occur in the digital
domain
b modelling fanout does occur, e.g. mux connects to 2 DB, or a stream that
also connects to a dp_bsn_monitor.
c components can connect using there default IO indexing like bg > mux, but
there are also use cases for connecting components per stream using
alterantive indexing, e.g. to use only one output of dp_split or e.g. to
connect bg[0] > mux[1] and bg[1] > mux[0]
d connections can be modelled by queues or pipes. The queue builds on top of
pipe, pipe simulates faster, is using pipe sufficient for our modelling
e where is the is the connection modelled, as a seperate object, as part of
every component snk (to support fanout)?
f the statement bg > mux > db has multple '>' connectors per statement, this
works because bg > mux returns the output of mux as input for db. Does this
properly reflect the digital domain.
g what does the connector '>' reflect, is it the data transport or also the
structure. The data transport function is important for the functional
simulation of the model. The structure function is important for
the code generation from the model.
h does the structure need hierarchy or does flat interconnect better match
the problem domain. For a multi node model using hierarchy seems
appropriate. Similar for creating higher level components in Python,
provided
h MyHDL uses the return of functions that model the RTL processes to create
the structure.
i what about defining also an '=' operator like in d = bg > mux. Does the '='
create hierarchy or is d merely an auxiliary variable. The purpose of
hierarchy is to facilitate reuse (i.e. multple instances) or to make the
code more clear.
j what about using '(' and ')' like in d = bg > mux > (db0, db1), is that
useful or too much
k having 800 processes per machine seems sufficient, but can it been
increased and how.
l The model should reflect the digital problem domain, i.e. like a schematic.
this approach can help to decide what to model and how much. The model
(solution) should not be more complex than the reality (the problem).
- next steps:
DS investigate c)
HJP investigat b), d)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment