On Feb 16, 9:36 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Mon, 16 Feb 2009 05:21:37 -0800 (PST), jleslie48 wrote:
> >At this stage, this is mostly an exercise in controlling
> >mechanisms in a FPGA using VHDL.... the hammer and
> >chisel are what I need to learn.
>
> Fair enough. Good to try it on an example that has
> reasonably interesting control flow, but where the
> data manipulation is trivial.
>
>
>
> >"Consider a redirection table, where the addresses of
> >the various strings are stored in a simple lookup table
> >indexed by label number. "
>
> >That is exactly what I did, I think. Actually I had a question about
> >that.
> >I used your [JB's] function CONTENTS as a template and created
> >function FIND_LABEL:
>
> >---------------------------------------------------------------------
> > function find_label(pgm: t_ubyte_array) return t_lbl is
> > constant p: t_ubyte_array (0 to pgm'length-1) := pgm;
> > variable it: t_lbl;
> > begin
> > it := (others => 0);
> > for i in 0 to (p'length-2) loop
> > if (p(i)= op_label) then
> > it(p(i+1)) := i;
> > end if;
> > end loop;
> > return it;
> > end;
>
> Very nice. Give the synth tool lots of work to do.
> THAT is the payoff you get when software folk have
> struggled to understand how this works - they can
> easily see how to get some real mileage out of the
> compiler. I wish more of the design community were
> prepared to do the same :-)
>
> > -- The ROM contents, initialized from the generic
> > constant the_rom: t_rom := contents(the_program);
> > constant the_label: t_lbl := find_label(the_program);
>
> OK, you've used the function to initialize a constant
> (at the architecture or process level) so it gets
> executed at ELABORATION time - the COMPILER takes
> the hit, the hardware just sees a lookup table (ROM).
> You have written my "string address compiler" in VHDL!
> Now to add some compiler error checks (duplicate
> label definitions?) - consider using a VHDL assert
> statement for that:
>
> if (p(i)= op_label) then
> assert it(p(i+1)) = 0 -- Nothing there yet, I hope
> report "Duplicate label " & integer'image(p(i+1))
> & " at address " & integer'image(i+1)
> severity FAILURE;
> it(p(i+1)) := i;
> end if;
>
> will cause synthesis to fail on that error.
>
> By contrast, a constant declared in a function
> or procedure is evaluated afresh every time the
> subprogram is called, and therefore it typically
> costs the HARDWARE some effort (unless the compiler
> can see that it is truly invariant, and optimize
> the function away).
>
> >My question is, when (to use the term loosely) does this function
> >run (again using the term loosely) It seems to me that it only
> >"needs" to establish the arrays once, but I know the process is
> >alive always, is it constantly remaking the storage locations
> >the_rom and the_label over and over?
>
> See above. When considering VHDL you need to be very clear
> about the idea of ELABORATION - the last part of compilation,
> very roughly analogous to linking in C. At elaboration time,
> the instance hierarchy is constructed top-down. Constants
> are given their values, and then possibly used to determine
> the structure of child instances. Elaboration determines
> the hardware's structure, but does not represent activity
> within the hardware itself.
>
> Processes, on the other hand, execute in response to
> signal-change events and therefore represent real
> hardware activity.
>
> >It probably doesn't make a difference
>
> It most certainly does! Remember that any piece of VHDL
> that does not contain a "wait" statement must execute in
> zero simulated time, and therefore must represent the
> behaviour of a piece of combinational logic in hardware.
>
> What nightmare hardware would be needed to determine the
> set of label addresses as a boolean-logic function of the
> input string? Aaaaargh!
>
> > I'm thinking the conveyor-belt
> >linear system of cpu programming. In that case you don't want to keep
> >parsing the same string over and over, but in the FPGA world it
> >doesn't make a difference.
>
> Eh?????!!!!! See above....
>
>
>
> >"Wouldn't it have
> >been way, way easier to write a little "compiler" to do
> >all the necessary string length and address calculations
> >in advance, generating a piece of VHDL code (or a Xilinx
> >memory-format file) to graft into your project, so that
> >you could stick with the nice simple "goto address"
> >hardware? Scanning the program to find its labels
> >must be a non-trivial overhead. "
>
> >Again, I'm pretty sure that is what I did. I'm not
> >sure what you mean by nice simple "goto address"
> >to me the simplest way was to drop a marker at
> >the beginning of whatever message I want and
> >reference that marker with the GOTOL command.
> >In this way, all the string and address calcuations
> >ARE calculated as you suggested.
>
> More or less, but you still need to access your
> indirection table once per jump, whereas you *could*
> precalculate the jump addresses and avoid the table
> lookup. Imagine this "program":
>
> MSG "Hello"
> GOTO LabelA
> LABEL LabelB
> MSG "At B"
> HALT
> LABEL LabelA
> MSG "At A"
> GOTO LabelB
>
> Now, I could imagine compiling this into the "machine code"
>
> address code
> 0 MSG
> 1 "Hello"
> 6 EOM
> 7 GOTO 16 // GOTO LabelA
> 9 MSG // LabelB is at address 9
> 10 "At B"
> 14 EOM
> 15 HALT
> 16 MSG // LabelA is at address 16
> 17 "At A"
> 21 EOM
> 22 GOTO 9 // GOTO LabelB
>
> No label lookup table is now required, right?
> All the "compilation" work was done by the synthesis
> tool, at elaboration time, leaving the minimum of
> run-time hardware activity and therefore saving
> hardware and allowing for higher clock rates.
>
> Maybe you've already done this and/or more, so please
> ignore me if I'm telling you stuff you already know.
>
> Enjoy
> --
> Jonathan Bromley, Consultant
>
> DOULOS - Developing Design Know-how
> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> The contents of this message may contain personal views which
> are not the views of Doulos Ltd., unless specifically stated.
Yes, these are the ideas I've been formulating all weekend long.
we are [finally] moving to the same page.
"Now to add some compiler error checks (duplicate
label definitions?) - consider using a VHDL assert "
Most definitely. My code is far from bullet-proof. My first
self-inflicted wound was this:
-- A LABEL is a marker, a noop, but used for the GOTOL lbl
constant op_LABEL : t_ubyte := 76; -- 'L'
and since my label parser was stupid, ANY 'L' character, including
the ones as part of the data of an op_MESSAGE generated label
lookups, and as the character after a 'L' character did not
necessarily
fit into the boundaries of my lookup table, this crashed big time.
Now the correct course of action would be to actually define a grammar
for the "the_program" command set, with context specifiers and full
language specfications. for example:
the_program ==> <set_of_comands>
<set_of_commands> ==> [<simple_command> [simple_command_tail]]
<simple_command_tail> ==> [& <simple_command>]
<simple_command> ==> [ op_HALT |
op_DELAY <op_delay_data> |
...
etc.
however, I just took a tactical approach; made sure that my op_LABEL
tag was in a disjoint set from any possible data value. Simply put, I
made
sure that the op_LABEL command would never be in any part of the
program in another context by changing the constant to:
-- A LABEL is a marker, a noop, but used for the GOTOL lbl
constant op_LABEL : t_ubyte := 176; --NON standard ascii char.
the value 176 ~should~ never be in an ascii string in the_program. Now
if an application programmer should want a delay of of 176 units, well
then
I'm gonna slap him about the head and neck...
Of course this is a cheat, but it will work with just being a little
careful.
"Imagine this "program":
MSG "Hello"
GOTO LabelA
LABEL LabelB
MSG "At B"
HALT
LABEL LabelA
MSG "At A"
GOTO LabelB "
Not exactly what I had imagined, I had imagined it this way:
LABEL xx1:
MSG "the quick brown fox"
WGOTOL <noop>
LABEL xx2:
MSG "Mary had a little lamb"
WGOTOL <noop>
...
LABEL xxn:
MSG "Its the end of the world as we know it."
WGOTOL <noop>
where WGOTOL is similar to your
op_WAIT_FOR_CHAR
only instead of getting its data fields from the next byte
and the rx_data line, the entity would have a new "input" of the
print_target_label, which would have the value of
xx1, xx2, ... xxn
and thus send the MSG out the uart and then spin waiting for the
next update to print_target_label.
Should have that done shortly.
Sincerely,
Jon
sincerely,
Jon