<div dir="ltr">Hallo,<div>I like to get some comment here from the people in the know!</div><div><br><div>On the matter of memory mapping things in any Oberon.</div><div><br></div><div>As an introduction: </div><div>1. Oberon has not got a linker (except in some cases Chris mentioned). Linking is done dynamically as and when the system decides a module is needed.</div><div>2. In Oberon there is no clear boundary between &quot;runtime library&quot;, &quot;operating system&quot; and &quot;user-land&quot; like we have in linux or any other os. On the contrary the boundary is very fluid. What I called the runtime just now, might just as well be called a more permanent part of user-land (in the sense that is is almost always loaded) The only real distinction is &quot;boot-loader&quot; and &quot;applications&quot;</div><div>3. Where in the past the compiler was attacked, it was to prove a radically new concept: Oberon-V4, Xoberon, Component Pascal and Active Oberon come to mind. In the greater scheme of things Oberon 7 is merely a revision of Oberon 2.</div><div>So in other words: the number of language dialects have been kept to a minimum, although there are perhaps too many already.</div><div><br></div><div>Although I might partly agree that to be able to assign an address attribute to a variable sounds like a nifty idea, I am not in favour of it. Because then we should rather look more generally into the matter of assigning attributes to things. And that will open up a huge can of worms. In fact such a huge can, that I advise to use Ada instead, where you have such a need.</div><div>Secondly my experience is that it needs solid planning and strict discipline to keep all the address attributes together in one place, so the whole circus stays readable and maintainable.</div><div><br></div><div>This leaves us with the boot-loader / application space to reach our goal, since using a linker is a bit &#39;uncool&#39;, to be prevented where we do not need it.</div><div>That is why I proposed earlier to use a system-constants Module. It is neither here nor there if we create such a thing or not. The language stays the same and is readable and the program stays maintainable by anybody conversant with the art. It is just another part of &quot;application space&quot;. And the idea is widely portable.</div><div><br></div><div>In the same vein I like to propose that we have a careful look at the way modules get loaded. </div><div><br></div><div>Say we have a Module with only exportable variables that occupy a contiguous range in memory (like for memory mapped io), in fact for a different range of memory we might simply create another Module.</div><div>So we create pairs:</div><div>Range of memory -- Module,</div><div>Range of memory -- Module,<br></div><div>etc.</div><div>Now the only difficulty left is to actually get them loaded with their variables overlapping the range of memory we had in mind when we created the Module.</div><div><br></div><div>At this moment in time, having had a very brief look at the system software, I believe this is not too difficult to arrange.</div><div>Perhaps the system-constants Module might contain the table of pairs mentioned above, or we might find another acceptable way.</div><div><br></div><div>This idea might in fact also take care of hardware system flags under software control, like a cpu speed flag.</div><div>All you need to do is import the relevant module, and there you have your hardware-locked-in-place variables ready to be manipulated.</div><div><br></div><div>Advantages over most other schemes I know of:</div><div><br></div><div>1. We still don&#39;t need a linker. In fact the linker script, that great source of unknown darkness,  is replaced by the system-constants Module; and then only partly.</div><div><br></div><div>2. All address attributes to variables are of necessity  kept in one place. Any hardware locked variable is easily recognized in the program, since it is imported from one of these special modules. </div><div><br></div><div>3. a set of programs without hardware locked variables will still function as it always has, even if a system is modified to accept hardware-locked-variable modules. It is completely transparent. </div><div><br></div><div>4. The compiler is left alone, no need to break things that work!</div><div><br></div><div>5. the idea is easily ported to any embedded processor.</div><div><br></div><div>6. it is elegant and minimalistic, with maximum benefit.</div><div><br></div><div><br></div><div>Enjoy,</div><div><br></div><div>j.</div><div><br></div><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Aug 27, 2015 at 4:52 PM,  <span dir="ltr">&lt;<a href="mailto:skulski@pas.rochester.edu" target="_blank">skulski@pas.rochester.edu</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Juerg:<br>
<span class="">&gt; 1) sometimes it is necessary to put data in fast memory<br>
&gt; (I think you mean BRAM)<br>
</span>&gt; 2) you would like to process your ADC data (stored in BRAM)<br>
&gt;     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) 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 oscilloscope.) The<br>
data needs to be accessed in situ. Copying it to slow memory would render<br>
the instrument slow and unusable.<br>
<br>
The bottom line: there is need to map a BRAM to the processor&#39;s memory<br>
space. This has been discussed by Jan (thank you, Jan!). His prescription<br>
is low level. OK, let be it. But let me make it clear that moving 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 signal to<br>
slow the processor down to match the SRAM.<br>
<br>
&gt;From this discussion it follows that we need to map both the variables and<br>
the code to particular addresses. The mechanism for doing this needs 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>
<span class=""><br>
<br>
&gt; 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>
</span>Performance will be unacceptable. In our design we will use &quot;ping-pong<br>
buffers&quot; implemented in BRAM. When one BRAM buffer acquires the data, the<br>
previous data from the other buffer is being processed in situ.<br>
<span class=""><br>
&gt; - Jan proposes a copy approach BRAM to SRAM<br>
<br>
</span>Unacceptable for the performance reasons.<br>
<span class=""><br>
&gt; and then process by Oberon - Chris proposes a mapped memory aaproach.<br>
<br>
</span>This is the way.<br>
<span class=""><br>
<br>
&gt; To understand the Oberon memory layout have a look at figure 8.1 in<br>
chapter 8 of project oberon.<br>
&gt; You see basically that the Oberon system splits memory in four blocks A<br>
memory for module code<br>
&gt; B memory for procedure variables (called stack)<br>
&gt; C memory for dynamic variables allocated with NEW (called heap)<br>
&gt; D memory for IO (display frame buffer and IO registers)<br>
<br>
</span>We need to statically allocate variables to HW addresses. Would be really<br>
nice to have this facility for both the scalar variables (aka &quot;registers&quot;)<br>
and arrays which will be overlaid over BRAM blocks.<br>
<br>
Furthermore, we need the facility to specify that certain code is 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 &quot;system<br>
library&quot; of sorts, where the performance-critical code will be put and<br>
called by the &quot;slow code&quot; 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>
<span class=""><br>
<br>
&gt; This layout is flexibly established during booting by two constants in<br>
the<br>
&gt; boot record, called &quot;heapOrg&quot; and &quot;heapLimit&quot;.<br>
&gt; A starts at 0 and grows upwards<br>
&gt; B starts at heapOrg and grows downwards<br>
&gt; C starts at heapOrg and grows upward til heapLimit<br>
&gt; D starts at heapOrg+heapLimit<br>
&gt; Now, I think you don&#39;t like Jan&#39;s copy approach. So you could do the<br>
following memory map approach: Reduce &quot;heapLimit&quot; and map the memory<br>
range<br>
&gt; just below the VGA framebuffer to your BRAM (this mapping has to be done<br>
in Verilog)<br>
&gt; 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>
</span>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>
<span class=""><br>
Jan wrote:<br>
<br>
&gt;&gt; But we can do without a version for every toy about town<br>
<br>
</span>I am discussing features that may seem exotic to a computer scientist.<br>
These &quot;toys&quot; are not toys for an electrical engineer working with FPGAs.<br>
They are in fact fundamental in the realm of FPGA design. My point 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>
<div class="HOEnZb"><div class="h5">Wojtek<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>