diff --git a/tools/oneclick/prestudy/7_stream_simplex_2_comp_parallel.py b/tools/oneclick/prestudy/7_stream_simplex_2_comp_parallel.py new file mode 100644 index 0000000000000000000000000000000000000000..16388b28c987251f619d609583dad021c23894f1 --- /dev/null +++ b/tools/oneclick/prestudy/7_stream_simplex_2_comp_parallel.py @@ -0,0 +1,41 @@ +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() + diff --git a/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.doc b/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.doc new file mode 100644 index 0000000000000000000000000000000000000000..a01563c8fcd84a400096b037dc099d930c31287c Binary files /dev/null and b/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.doc differ diff --git a/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.pdf b/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fd7b263599718ddfa5ad7512d1f18f87c990bc64 Binary files /dev/null and b/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.pdf differ diff --git a/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.vsd b/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.vsd new file mode 100644 index 0000000000000000000000000000000000000000..060f08c2a0d0335f8381ad52cda76e42ee236286 Binary files /dev/null and b/tools/oneclick/prestudy/ASTRON_SP_056_One_Click_Design_Flow_Specification.vsd differ diff --git a/tools/oneclick/prestudy/ASTRON_SP_057_RadioHDL_Firmware_Directory_Structure.doc b/tools/oneclick/prestudy/ASTRON_SP_057_RadioHDL_Firmware_Directory_Structure.doc new file mode 100644 index 0000000000000000000000000000000000000000..6acb548c9de310e34c245bca50ded8bbdfabf5e8 Binary files /dev/null and b/tools/oneclick/prestudy/ASTRON_SP_057_RadioHDL_Firmware_Directory_Structure.doc differ diff --git a/tools/oneclick/prestudy/ASTRON_SP_057_RadioHDL_Firmware_Directory_Structure.pdf b/tools/oneclick/prestudy/ASTRON_SP_057_RadioHDL_Firmware_Directory_Structure.pdf new file mode 100644 index 0000000000000000000000000000000000000000..db53cb5ca83ef0cf63db8bcfb6f5aa2d5598ec91 Binary files /dev/null and b/tools/oneclick/prestudy/ASTRON_SP_057_RadioHDL_Firmware_Directory_Structure.pdf differ diff --git a/tools/oneclick/prestudy/multithreads.py b/tools/oneclick/prestudy/multithreads.py new file mode 100644 index 0000000000000000000000000000000000000000..ce730cee361ec1cf1fd34c279fb123ff7e4c2a87 --- /dev/null +++ b/tools/oneclick/prestudy/multithreads.py @@ -0,0 +1,154 @@ +############################################################################### +# +# 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() + + + + diff --git a/tools/oneclick/prestudy/one_click_concept.py b/tools/oneclick/prestudy/one_click_concept.py new file mode 100644 index 0000000000000000000000000000000000000000..7bfdb7da141d0d8c75bd86ced14a6114f484c29c --- /dev/null +++ b/tools/oneclick/prestudy/one_click_concept.py @@ -0,0 +1,74 @@ +# 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 + diff --git a/tools/oneclick/prestudy/oneclick_prestudy_readme.txt b/tools/oneclick/prestudy/oneclick_prestudy_readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..d4a7308e1d72f924e88f7bb91970cc4e2dc38bfd --- /dev/null +++ b/tools/oneclick/prestudy/oneclick_prestudy_readme.txt @@ -0,0 +1,94 @@ +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) +