<div dir="ltr">Hallo Peter,<div><br></div><div>Don't know whether you followed the thread about Wojtek'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'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>> 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>> 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>> I don'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 'Project Oberon' 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 'boot parameter' 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>> As soon as you have RECORDS or ARRAYS </div><div><br></div><div>I am aware of that limitation.</div><div><br></div><div>> This has to be proved.</div><div><br></div><div>Obviously.</div><div><br></div><div>> I don'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'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"><<a href="mailto:PeterMatthias@web.de" target="_blank">PeterMatthias@web.de</a>></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>
> Hallo,<br>
> I like to get some comment here from the people in the know!<br>
><br>
> On the matter of memory mapping things in any Oberon.<br>
><br>
> As an introduction:<br>
> 1. Oberon has not got a linker (except in some cases Chris mentioned).<br>
> Linking is done dynamically as and when the system decides a module is<br>
> 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>
> 2. In Oberon there is no clear boundary between "runtime library",<br>
> "operating system" and "user-land" like we have in linux or any other<br>
> os. On the contrary the boundary is very fluid. What I called the<br>
> runtime just now, might just as well be called a more permanent part of<br>
> user-land (in the sense that is is almost always loaded) The only real<br>
> distinction is "boot-loader" and "applications"<br>
<br>
</span>Yes, no clear boundary between Kernel, OS, Libraries and Application.<br>
<span class=""><br>
> 3. Where in the past the compiler was attacked, it was to prove a<br>
> radically new concept: Oberon-V4, Xoberon, Component Pascal and Active<br>
> Oberon come to mind. In the greater scheme of things Oberon 7 is merely<br>
> a revision of Oberon 2.<br>
> So in other words: the number of language dialects have been kept to a<br>
> minimum, although there are perhaps too many already.<br>
<br>
</span>At least too many per user ;-)<br>
<span class=""><br>
> Although I might partly agree that to be able to assign an address<br>
> attribute to a variable sounds like a nifty idea, I am not in favour of<br>
> it. Because then we should rather look more generally into the matter of<br>
> assigning attributes to things. And that will open up a huge can of<br>
> worms. In fact such a huge can, that I advise to use Ada instead, where<br>
> you have such a need.<br>
> Secondly my experience is that it needs solid planning and strict<br>
> discipline to keep all the address attributes together in one place, so<br>
> the whole circus stays readable and maintainable.<br>
><br>
> This leaves us with the boot-loader / application space to reach our<br>
> goal, since using a linker is a bit 'uncool', to be prevented where we<br>
> do not need it.<br>
> That is why I proposed earlier to use a system-constants Module. It is<br>
> neither here nor there if we create such a thing or not. The language<br>
> stays the same and is readable and the program stays maintainable by<br>
> anybody conversant with the art. It is just another part of "application<br>
> space". And the idea is widely portable.<br>
<br>
</span>System parts in application space seems a bad idea to me.<br>
<span class=""><br>
> In the same vein I like to propose that we have a careful look at the<br>
> way modules get loaded.<br>
><br>
> Say we have a Module with only exportable variables that occupy a<br>
> contiguous range in memory (like for memory mapped io), in fact for a<br>
> different range of memory we might simply create another Module.<br>
> So we create pairs:<br>
> Range of memory -- Module,<br>
> Range of memory -- Module,<br>
> etc.<br>
> Now the only difficulty left is to actually get them loaded with their<br>
> variables overlapping the range of memory we had in mind when we created<br>
> the Module.<br>
<br>
</span>Not the only one...<br>
<span class=""><br>
> At this moment in time, having had a very brief look at the system<br>
> software, I believe this is not too difficult to arrange.<br>
> Perhaps the system-constants Module might contain the table of pairs<br>
> mentioned above, or we might find another acceptable way.<br>
><br>
> This idea might in fact also take care of hardware system flags under<br>
> software control, like a cpu speed flag.<br>
> All you need to do is import the relevant module, and there you have<br>
> your hardware-locked-in-place variables ready to be manipulated.<br>
><br>
> Advantages over most other schemes I know of:<br>
><br>
> 1. We still don't need a linker. In fact the linker script, that great<br>
> source of unknown darkness, is replaced by the system-constants Module;<br>
> and then only partly.<br>
<br>
</span>I don't see how this could work.<br>
<span class=""><br>
> 2. All address attributes to variables are of necessity kept in one<br>
> place. Any hardware locked variable is easily recognized in the program,<br>
> 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>
> 3. a set of programs without hardware locked variables will still<br>
> function as it always has, even if a system is modified to accept<br>
> hardware-locked-variable modules. It is completely transparent.<br>
><br>
> 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>
> 5. the idea is easily ported to any embedded processor.<br>
<br>
</span>This has to be proved.<br>
<span class=""><br>
> 6. it is elegant and minimalistic, with maximum benefit.<br>
<br>
</span>I don'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>
><br>
> Enjoy,<br>
><br>
> j.<br>
><br>
><br>
><br>
> On Thu, Aug 27, 2015 at 4:52 PM, <<a href="mailto:skulski@pas.rochester.edu">skulski@pas.rochester.edu</a><br>
</span><div><div class="h5">> <mailto:<a href="mailto:skulski@pas.rochester.edu">skulski@pas.rochester.edu</a>>> wrote:<br>
><br>
> Juerg:<br>
> > 1) sometimes it is necessary to put data in fast memory<br>
> > (I think you mean BRAM)<br>
> > 2) you would like to process your ADC data (stored in BRAM)<br>
> > in Oberon.<br>
><br>
> Let me make it clear for those in the audience who are new to the FPGA<br>
> design. BRAM is a dual port memory. It has many uses which I can discuss<br>
> if there is interest. Here we are talking of data acquisition (DAQ)<br>
> with a<br>
> few nanoseconds per data sample. A typical high performance DAQ design<br>
> uses BRAM port A to write data from the converter, and it uses port B to<br>
> access the data when the DAQ stops. (Think of a digital<br>
> oscilloscope.) The<br>
> data needs to be accessed in situ. Copying it to slow memory would<br>
> render<br>
> the instrument slow and unusable.<br>
><br>
> The bottom line: there is need to map a BRAM to the processor's memory<br>
> space. This has been discussed by Jan (thank you, Jan!). His<br>
> prescription<br>
> is low level. OK, let be it. But let me make it clear that moving<br>
> the data<br>
> is not permitted. Accessing the data without moving is necessary.<br>
><br>
> Furthermore, the code which implements the data processing needs to be<br>
> executed from BRAM as well. (It will be a different block of BRAM.) I<br>
> think that RISC5 can run at some 100+ MHz when it executes from BRAM. We<br>
> have looked at the RISC5 Verilog and we see that it needs to be reworked<br>
> in this direction. Hopefully it can reach 100+ MHz from BRAM. Then the<br>
> slow code can be put into off-chip SRAM and we can use the stall<br>
> signal to<br>
> slow the processor down to match the SRAM.<br>
><br>
> >From this discussion it follows that we need to map both the<br>
> variables and<br>
> the code to particular addresses. The mechanism for doing this needs<br>
> to be<br>
> specified somehow. Of course we can take the Oberon System and hack it,<br>
> but this would be ugly. I am hoping that a sort of agreed-upon approach<br>
> will emerge from this discussion.<br>
><br>
><br>
> > Oberon works with what you call slow memory. So if you want to process<br>
> your fast data with the slow Oberon, why not put the data in the slow<br>
> memory in the first place?<br>
><br>
> Performance will be unacceptable. In our design we will use "ping-pong<br>
> buffers" implemented in BRAM. When one BRAM buffer acquires the<br>
> data, the<br>
> previous data from the other buffer is being processed in situ.<br>
><br>
> > - Jan proposes a copy approach BRAM to SRAM<br>
><br>
> Unacceptable for the performance reasons.<br>
><br>
> > and then process by Oberon - Chris proposes a mapped memory aaproach.<br>
><br>
> This is the way.<br>
><br>
><br>
> > To understand the Oberon memory layout have a look at figure 8.1 in<br>
> chapter 8 of project oberon.<br>
> > You see basically that the Oberon system splits memory in four blocks A<br>
> memory for module code<br>
> > B memory for procedure variables (called stack)<br>
> > C memory for dynamic variables allocated with NEW (called heap)<br>
> > D memory for IO (display frame buffer and IO registers)<br>
><br>
> We need to statically allocate variables to HW addresses. Would be<br>
> really<br>
> nice to have this facility for both the scalar variables (aka<br>
> "registers")<br>
> and arrays which will be overlaid over BRAM blocks.<br>
><br>
> Furthermore, we need the facility to specify that certain code is<br>
> executed<br>
> from BRAM to gain performance. This can be specified per module to keep<br>
> with the modular spirit of the language. A finer granularity would be<br>
> complicated and not necessary.<br>
><br>
> Here we are talking of a factor 5x in performance between BRAM and<br>
> external SRAM. This is not a small optimization. It is quite crucial.<br>
><br>
> At present there is the single MODULE* which is locked into BRAM, so we<br>
> are almost there. I hope that we can use the MODULE* as the "system<br>
> library" of sorts, where the performance-critical code will be put and<br>
> called by the "slow code" that lives in SRAM. However, it is a hack. It<br>
> would be really nice if the memory allocation could be specified for<br>
> regular modules as well, on a per-module basis.<br>
><br>
><br>
> > This layout is flexibly established during booting by two constants in<br>
> the<br>
> > boot record, called "heapOrg" and "heapLimit".<br>
> > A starts at 0 and grows upwards<br>
> > B starts at heapOrg and grows downwards<br>
> > C starts at heapOrg and grows upward til heapLimit<br>
> > D starts at heapOrg+heapLimit<br>
> > Now, I think you don't like Jan's copy approach. So you could do the<br>
> following memory map approach: Reduce "heapLimit" and map the memory<br>
> range<br>
> > just below the VGA framebuffer to your BRAM (this mapping has to be done<br>
> in Verilog)<br>
> > You can declare in Oberon a safe TYPE to your ADC data (e.g. POINTER TO<br>
> ARRAY 256 OF BYTE) and allocate the start address of your mapped BRAM<br>
> memory to a pointer variable.<br>
><br>
> I think this is all good. It is a bit of a hack put on top the classic<br>
> design, but it looks workable to me. Thank you for the suggestions.<br>
><br>
> Jan wrote:<br>
><br>
> >> But we can do without a version for every toy about town<br>
><br>
> I am discussing features that may seem exotic to a computer scientist.<br>
> These "toys" are not toys for an electrical engineer working with FPGAs.<br>
> They are in fact fundamental in the realm of FPGA design. My point<br>
> is that<br>
> the FPGA Oberon System is running in the FPGA. It would be good to know<br>
> how the FPGA Oberon can help using the FPGA to the fullest extent. If it<br>
> does then it will become a much more attractive tool.<br>
><br>
> Thank you,<br>
> Wojtek<br>
><br>
><br>
> --<br>
</div></div>> <a href="mailto:Oberon@lists.inf.ethz.ch">Oberon@lists.inf.ethz.ch</a> <mailto:<a href="mailto:Oberon@lists.inf.ethz.ch">Oberon@lists.inf.ethz.ch</a>> mailing<br>
<div class="HOEnZb"><div class="h5">> 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>
><br>
><br>
><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>
><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>