<div dir="ltr">Hallo Peter,<div><br></div><div>Don&#39;t know whether you followed the thread about Wojtek&#39;s needs in FPGA programming.</div><div>This whole write up was mainly addressed to that need, and obviously to generate discussion. So thank you for replying.</div><div><br></div><div>I am very aware of Native Oberon&#39;s way of doing things. If you look long and hard you will still find my name in some beta-testers list from the time that Peter Muller ran Native + Gadgets.</div><div><br></div><div><div>&gt; a static one for the inner core</div></div><div><br></div><div>This seems one of the trade secrets of ETH :) never found any code yet. I am aware it exists.</div><div><br></div><div>&gt; Not the only one...</div><div><br></div><div>To be studied. I am always enthusiastic that I will deliver, from happy experience lets say.</div><div><br></div><div>&gt; I don&#39;t see how this could work.</div><div><br></div><div>Perhaps calling it the linker script leads people astray.</div><div>In an earlier post I wrote this:</div><div><div>-- So this morning I had a quick look in chapter 14 of the new &#39;Project Oberon&#39; and in the source files </div><div>-- that control the boot process. At the moment most addresses are hard wired and difficult to decipher for a novice.</div><div>-- So I think what might be done is: make a &#39;boot parameter&#39; module, that exports just the required variables </div><div>--  with copious explanation --,  that is imported into the regular bootloader, Kernel etc.</div></div><div>This was in response to the need to execute code from high speed Bram and the need to memory map hardware on his FPGA.</div><div><br></div><div>&gt; As soon as you have RECORDS or ARRAYS </div><div><br></div><div>I am aware of that limitation.</div><div><br></div><div>&gt; This has to be proved.</div><div><br></div><div>Obviously.</div><div><br></div><div>&gt; I don&#39;t see any benefit at all. </div><div><br></div><div>Ultimately not for me to decide at this moment. I would have to see the exact requirements and do a comparative study of the problem, and do some timing comparisons _in this specific problem space_ before deciding.</div><div><br></div><div>I do think that Wojtek is pushing the limits here, but then if the limits do not get pushed there will be no invention an we all slowly doze off.</div><div><br></div><div>So to some up my response to your most valued critique:</div><div>1. Yes it is a bad idea to modify the Oberon runtime, but I feel it might be possible. </div><div>2. I agree with Wojtek that in order to successfully program FPGA&#39;s some unorthodox ideas are needed.</div><div>    Note in this respect the length of time the group needed to come up with an acceptable replacement </div><div>    for the original FPGA.  Not very encouraging.</div><div>2. For a one off design, to modify the runtime is infinitely more preferable than modifying the compiler or even linking a static image that then has to be moved part wise on startup.</div><div>3. Some more study is needed of the problem, before we commit ourselves this way or that way.</div><div><br></div><div>Cheers,</div><div><br></div><div>j.</div><div><br></div><div><br></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Aug 28, 2015 at 3:48 PM, Peter Matthias <span dir="ltr">&lt;<a href="mailto:PeterMatthias@web.de" target="_blank">PeterMatthias@web.de</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
<br>
Am 28.08.2015 um 13:29 schrieb Jan de Kruyf:<br>
&gt; Hallo,<br>
&gt; I like to get some comment here from the people in the know!<br>
&gt;<br>
&gt; On the matter of memory mapping things in any Oberon.<br>
&gt;<br>
&gt; As an introduction:<br>
&gt; 1. Oberon has not got a linker (except in some cases Chris mentioned).<br>
&gt; Linking is done dynamically as and when the system decides a module is<br>
&gt; needed.<br>
<br>
</span>Oberon not only has one linker, it has two linker. a static one for the<br>
inner core and a dynamic one for the rest.<br>
<span class=""><br>
&gt; 2. In Oberon there is no clear boundary between &quot;runtime library&quot;,<br>
&gt; &quot;operating system&quot; and &quot;user-land&quot; like we have in linux or any other<br>
&gt; os. On the contrary the boundary is very fluid. What I called the<br>
&gt; runtime just now, might just as well be called a more permanent part of<br>
&gt; user-land (in the sense that is is almost always loaded) The only real<br>
&gt; distinction is &quot;boot-loader&quot; and &quot;applications&quot;<br>
<br>
</span>Yes, no clear boundary between Kernel, OS, Libraries and Application.<br>
<span class=""><br>
&gt; 3. Where in the past the compiler was attacked, it was to prove a<br>
&gt; radically new concept: Oberon-V4, Xoberon, Component Pascal and Active<br>
&gt; Oberon come to mind. In the greater scheme of things Oberon 7 is merely<br>
&gt; a revision of Oberon 2.<br>
&gt; So in other words: the number of language dialects have been kept to a<br>
&gt; minimum, although there are perhaps too many already.<br>
<br>
</span>At least too many per user ;-)<br>
<span class=""><br>
&gt; Although I might partly agree that to be able to assign an address<br>
&gt; attribute to a variable sounds like a nifty idea, I am not in favour of<br>
&gt; it. Because then we should rather look more generally into the matter of<br>
&gt; assigning attributes to things. And that will open up a huge can of<br>
&gt; worms. In fact such a huge can, that I advise to use Ada instead, where<br>
&gt; you have such a need.<br>
&gt; Secondly my experience is that it needs solid planning and strict<br>
&gt; discipline to keep all the address attributes together in one place, so<br>
&gt; the whole circus stays readable and maintainable.<br>
&gt;<br>
&gt; This leaves us with the boot-loader / application space to reach our<br>
&gt; goal, since using a linker is a bit &#39;uncool&#39;, to be prevented where we<br>
&gt; do not need it.<br>
&gt; That is why I proposed earlier to use a system-constants Module. It is<br>
&gt; neither here nor there if we create such a thing or not. The language<br>
&gt; stays the same and is readable and the program stays maintainable by<br>
&gt; anybody conversant with the art. It is just another part of &quot;application<br>
&gt; space&quot;. And the idea is widely portable.<br>
<br>
</span>System parts in application space seems a bad idea to me.<br>
<span class=""><br>
&gt; In the same vein I like to propose that we have a careful look at the<br>
&gt; way modules get loaded.<br>
&gt;<br>
&gt; Say we have a Module with only exportable variables that occupy a<br>
&gt; contiguous range in memory (like for memory mapped io), in fact for a<br>
&gt; different range of memory we might simply create another Module.<br>
&gt; So we create pairs:<br>
&gt; Range of memory -- Module,<br>
&gt; Range of memory -- Module,<br>
&gt; etc.<br>
&gt; Now the only difficulty left is to actually get them loaded with their<br>
&gt; variables overlapping the range of memory we had in mind when we created<br>
&gt; the Module.<br>
<br>
</span>Not the only one...<br>
<span class=""><br>
&gt; At this moment in time, having had a very brief look at the system<br>
&gt; software, I believe this is not too difficult to arrange.<br>
&gt; Perhaps the system-constants Module might contain the table of pairs<br>
&gt; mentioned above, or we might find another acceptable way.<br>
&gt;<br>
&gt; This idea might in fact also take care of hardware system flags under<br>
&gt; software control, like a cpu speed flag.<br>
&gt; All you need to do is import the relevant module, and there you have<br>
&gt; your hardware-locked-in-place variables ready to be manipulated.<br>
&gt;<br>
&gt; Advantages over most other schemes I know of:<br>
&gt;<br>
&gt; 1. We still don&#39;t need a linker. In fact the linker script, that great<br>
&gt; source of unknown darkness,  is replaced by the system-constants Module;<br>
&gt; and then only partly.<br>
<br>
</span>I don&#39;t see how this could work.<br>
<span class=""><br>
&gt; 2. All address attributes to variables are of necessity  kept in one<br>
&gt; place. Any hardware locked variable is easily recognized in the program,<br>
&gt; since it is imported from one of these special modules.<br>
<br>
</span>For variables of basic types this might work.<br>
<span class=""><br>
&gt; 3. a set of programs without hardware locked variables will still<br>
&gt; function as it always has, even if a system is modified to accept<br>
&gt; hardware-locked-variable modules. It is completely transparent.<br>
&gt;<br>
&gt; 4. The compiler is left alone, no need to break things that work!<br>
<br>
</span>As soon as you have RECORDS or ARRAYS the compiler has to be involved.<br>
The addresses would have to be some kind of pointers. Records have a tag<br>
the compiler has to be aware of. Array have size information as first<br>
data...<br>
<span class=""><br>
&gt; 5. the idea is easily ported to any embedded processor.<br>
<br>
</span>This has to be proved.<br>
<span class=""><br>
&gt; 6. it is elegant and minimalistic, with maximum benefit.<br>
<br>
</span>I don&#39;t see any benefit at all. Hardware programming is inherently<br>
unsafe. Adding type safety to its registers just adds nothing. Native<br>
Oberon shows that hardware driver easily can be well abstracted and<br>
written in a module.<br>
<br>
Regards,<br>
        Peter<br>
<span class=""><br>
&gt;<br>
&gt; Enjoy,<br>
&gt;<br>
&gt; j.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; On Thu, Aug 27, 2015 at 4:52 PM, &lt;<a href="mailto:skulski@pas.rochester.edu">skulski@pas.rochester.edu</a><br>
</span><div><div class="h5">&gt; &lt;mailto:<a href="mailto:skulski@pas.rochester.edu">skulski@pas.rochester.edu</a>&gt;&gt; wrote:<br>
&gt;<br>
&gt;     Juerg:<br>
&gt;     &gt; 1) sometimes it is necessary to put data in fast memory<br>
&gt;     &gt; (I think you mean BRAM)<br>
&gt;      &gt; 2) you would like to process your ADC data (stored in BRAM)<br>
&gt;      &gt;     in Oberon.<br>
&gt;<br>
&gt;     Let me make it clear for those in the audience who are new to the FPGA<br>
&gt;     design. BRAM is a dual port memory. It has many uses which I can discuss<br>
&gt;     if there is interest. Here we are talking of data acquisition (DAQ)<br>
&gt;     with a<br>
&gt;     few nanoseconds per data sample. A typical high performance DAQ design<br>
&gt;     uses BRAM port A to write data from the converter, and it uses port B to<br>
&gt;     access the data when the DAQ stops. (Think of a digital<br>
&gt;     oscilloscope.) The<br>
&gt;     data needs to be accessed in situ. Copying it to slow memory would<br>
&gt;     render<br>
&gt;     the instrument slow and unusable.<br>
&gt;<br>
&gt;     The bottom line: there is need to map a BRAM to the processor&#39;s memory<br>
&gt;     space. This has been discussed by Jan (thank you, Jan!). His<br>
&gt;     prescription<br>
&gt;     is low level. OK, let be it. But let me make it clear that moving<br>
&gt;     the data<br>
&gt;     is not permitted. Accessing the data without moving is necessary.<br>
&gt;<br>
&gt;     Furthermore, the code which implements the data processing needs to be<br>
&gt;     executed from BRAM as well. (It will be a different block of BRAM.) I<br>
&gt;     think that RISC5 can run at some 100+ MHz when it executes from BRAM. We<br>
&gt;     have looked at the RISC5 Verilog and we see that it needs to be reworked<br>
&gt;     in this direction. Hopefully it can reach 100+ MHz from BRAM. Then the<br>
&gt;     slow code can be put into off-chip SRAM and we can use the stall<br>
&gt;     signal to<br>
&gt;     slow the processor down to match the SRAM.<br>
&gt;<br>
&gt;      &gt;From this discussion it follows that we need to map both the<br>
&gt;     variables and<br>
&gt;     the code to particular addresses. The mechanism for doing this needs<br>
&gt;     to be<br>
&gt;     specified somehow. Of course we can take the Oberon System and hack it,<br>
&gt;     but this would be ugly. I am hoping that a sort of agreed-upon approach<br>
&gt;     will emerge from this discussion.<br>
&gt;<br>
&gt;<br>
&gt;     &gt; Oberon works with what you call slow memory. So if you want to process<br>
&gt;     your fast data with the slow Oberon, why not put the data in the slow<br>
&gt;     memory in the first place?<br>
&gt;<br>
&gt;     Performance will be unacceptable. In our design we will use &quot;ping-pong<br>
&gt;     buffers&quot; implemented in BRAM. When one BRAM buffer acquires the<br>
&gt;     data, the<br>
&gt;     previous data from the other buffer is being processed in situ.<br>
&gt;<br>
&gt;     &gt; - Jan proposes a copy approach BRAM to SRAM<br>
&gt;<br>
&gt;     Unacceptable for the performance reasons.<br>
&gt;<br>
&gt;     &gt; and then process by Oberon - Chris proposes a mapped memory aaproach.<br>
&gt;<br>
&gt;     This is the way.<br>
&gt;<br>
&gt;<br>
&gt;     &gt; To understand the Oberon memory layout have a look at figure 8.1 in<br>
&gt;     chapter 8 of project oberon.<br>
&gt;     &gt; You see basically that the Oberon system splits memory in four blocks A<br>
&gt;     memory for module code<br>
&gt;     &gt; B memory for procedure variables (called stack)<br>
&gt;     &gt; C memory for dynamic variables allocated with NEW (called heap)<br>
&gt;     &gt; D memory for IO (display frame buffer and IO registers)<br>
&gt;<br>
&gt;     We need to statically allocate variables to HW addresses. Would be<br>
&gt;     really<br>
&gt;     nice to have this facility for both the scalar variables (aka<br>
&gt;     &quot;registers&quot;)<br>
&gt;     and arrays which will be overlaid over BRAM blocks.<br>
&gt;<br>
&gt;     Furthermore, we need the facility to specify that certain code is<br>
&gt;     executed<br>
&gt;     from BRAM to gain performance. This can be specified per module to keep<br>
&gt;     with the modular spirit of the language. A finer granularity would be<br>
&gt;     complicated and not necessary.<br>
&gt;<br>
&gt;     Here we are talking of a factor 5x in performance between BRAM and<br>
&gt;     external SRAM. This is not a small optimization. It is quite crucial.<br>
&gt;<br>
&gt;     At present there is the single MODULE* which is locked into BRAM, so we<br>
&gt;     are almost there. I hope that we can use the MODULE* as the &quot;system<br>
&gt;     library&quot; of sorts, where the performance-critical code will be put and<br>
&gt;     called by the &quot;slow code&quot; that lives in SRAM. However, it is a hack. It<br>
&gt;     would be really nice if the memory allocation could be specified for<br>
&gt;     regular modules as well, on a per-module basis.<br>
&gt;<br>
&gt;<br>
&gt;     &gt; This layout is flexibly established during booting by two constants in<br>
&gt;     the<br>
&gt;     &gt; boot record, called &quot;heapOrg&quot; and &quot;heapLimit&quot;.<br>
&gt;     &gt; A starts at 0 and grows upwards<br>
&gt;     &gt; B starts at heapOrg and grows downwards<br>
&gt;     &gt; C starts at heapOrg and grows upward til heapLimit<br>
&gt;     &gt; D starts at heapOrg+heapLimit<br>
&gt;     &gt; Now, I think you don&#39;t like Jan&#39;s copy approach. So you could do the<br>
&gt;     following memory map approach: Reduce &quot;heapLimit&quot; and map the memory<br>
&gt;     range<br>
&gt;     &gt; just below the VGA framebuffer to your BRAM (this mapping has to be done<br>
&gt;     in Verilog)<br>
&gt;     &gt; You can declare in Oberon a safe TYPE to your ADC data (e.g. POINTER TO<br>
&gt;     ARRAY 256 OF BYTE) and allocate the start address of your mapped BRAM<br>
&gt;     memory to a pointer variable.<br>
&gt;<br>
&gt;     I think this is all good. It is a bit of a hack put on top the classic<br>
&gt;     design, but it looks workable to me. Thank you for the suggestions.<br>
&gt;<br>
&gt;     Jan wrote:<br>
&gt;<br>
&gt;     &gt;&gt; But we can do without a version for every toy about town<br>
&gt;<br>
&gt;     I am discussing features that may seem exotic to a computer scientist.<br>
&gt;     These &quot;toys&quot; are not toys for an electrical engineer working with FPGAs.<br>
&gt;     They are in fact fundamental in the realm of FPGA design. My point<br>
&gt;     is that<br>
&gt;     the FPGA Oberon System is running in the FPGA. It would be good to know<br>
&gt;     how the FPGA Oberon can help using the FPGA to the fullest extent. If it<br>
&gt;     does  then it will become a much more attractive tool.<br>
&gt;<br>
&gt;     Thank you,<br>
&gt;     Wojtek<br>
&gt;<br>
&gt;<br>
&gt;     --<br>
</div></div>&gt;     <a href="mailto:Oberon@lists.inf.ethz.ch">Oberon@lists.inf.ethz.ch</a> &lt;mailto:<a href="mailto:Oberon@lists.inf.ethz.ch">Oberon@lists.inf.ethz.ch</a>&gt; mailing<br>
<div class="HOEnZb"><div class="h5">&gt;     list for ETH Oberon and related systems<br>
&gt;     <a href="https://lists.inf.ethz.ch/mailman/listinfo/oberon" rel="noreferrer" target="_blank">https://lists.inf.ethz.ch/mailman/listinfo/oberon</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; <a href="mailto:Oberon@lists.inf.ethz.ch">Oberon@lists.inf.ethz.ch</a> mailing list for ETH Oberon and related systems<br>
&gt; <a href="https://lists.inf.ethz.ch/mailman/listinfo/oberon" rel="noreferrer" target="_blank">https://lists.inf.ethz.ch/mailman/listinfo/oberon</a><br>
&gt;<br>
<br>
--<br>
<a href="mailto:Oberon@lists.inf.ethz.ch">Oberon@lists.inf.ethz.ch</a> mailing list for ETH Oberon and related systems<br>
<a href="https://lists.inf.ethz.ch/mailman/listinfo/oberon" rel="noreferrer" target="_blank">https://lists.inf.ethz.ch/mailman/listinfo/oberon</a><br>
</div></div></blockquote></div><br></div>