Author Topic: Game of waves  (Read 5683 times)

0 Members and 1 Guest are viewing this topic.

Offline kbeckerTopic starter

  • Contributor
  • Posts: 19
Game of waves
« on: April 26, 2014, 03:41:36 am »
Hey everyone,
When I was working on a new API for interactive tutorials I realized that I could create a little game, which I did :)
You can check it out at http://waves.pshdl.org


Karsten
 

Offline T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 22436
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: Game of waves
« Reply #1 on: April 26, 2014, 08:11:47 am »
Neet!

I like the idea.  I dare say it's disruptive.  You could potentially eliminate one entire year, perhaps more, from a typical EE/CE curricula branch by prescribing just a few weeks' dabbling in this thing.  (I mean, most places have those damned online math problem checker things, that never work and are always tedious to frustrating.  This isn't much different, though -- I expect -- a lot more lenient on the acceptable solution side!)

Plus if kids just randomly find this and pick up on it, maybe pair it with some cheapshit Arduino-esque things so there's even something to hold in ones' hand, you could make even more of it.

I assume you're interested in comments?...

One odd thing about just the first puzzle.  Not knowing the language and just guessing, my first instinct was "o = !a", which it turns out is a boolean negation.  Which isn't a bitwise negation.  I guess it implicitly casts one to the other, but the "hardware size" figure was massive, like 240-some-odd, whatever that means of course -- whereas the "~" version does indeed generate the 4 pictured.

I would like to know more about the "hardware size" number.  What actually does it represent?  Does that bear any relation to hardware that would synthesize IRL?  Is it closer to RTL level (where a latch array is roughly equivalent to an adder or multiplier block), or gate level (and what kind -- MSI/SSI, or like NAND level)?  Or neither, is it more of a software algorithmic result instead?  (Which may still be representative of the underlying logic, but in a broadly different way, of course.)

Real hardware will, of course, optimize the boolean example fully away, but will also have adders, multipliers and other macro logic available on the fabric, making certain other operations far easier than sheer logic implies (e.g., using a counting integer in "Slow me" gets... 100-200 I think it was, which really only needs a couple latches and a constant adder; versus a ripple counter, which got me 44).  Which is absolutely platform-dependent, of course -- I certainly wouldn't expect a game to simplify this sort of thing to that level!



The documentation... is rather terse and doesn't explain things very well.  It's completely upside-down; in trying to use the documentation with the game, I'm spending all my time at the bottom, scouring just the syntax and declarations -- the first four challenges don't even begin to require a header, import, package, module, body or any of the high level structure mentioned!

In particular, the form of an expression or statement is presented in an unfamiliar way; this looks like a mess:
Quote
«annotation*» «direction?» «register?» «type»
   «annotation*» id [«dimension»]* (= «defaultValue»)?
   (, «annotation*» id [«dimension»]* (= «defaultValue»)?)*;
I've not seen the guillemets used before; from what I can tell, I would normally write this with a more diverse selection of braces:
Quote
[in|out|inout|param|const] [register] {type} <name>[<arraysize>] [= <defaultvalue>] [, <name2>[<arraysize>][= <defaultvalue>] [, ...]];

Where:
- square brackets [] denote an optional item,
- curly braces {} denote a required item,
- items separated by | means, pick just one
- angle brackets <> denote a required, user-defined parameter (e.g., a name for a variable)

- [in|out|inout|param|const] is the direction or visibility of the variable (and the items are...)
- [register] is a keyword which, if used, denotes a registered (persistent/state/memory/latch type) variable
- {type} is the type to declare the variable as; the primitive types are (so and so...; or list them in the braces), and <hyperlink> about libraries and stuff
- <name> is the name of the variable to declare
- [<arraysize>] is an optional parameter to specify an array type variable; use square brackets e.g., the name looks like "myarray[31]"
- [= <defaultvalue>] is the default (initial? resetted?) value of the variable[1]
- additional variables of the same {type} can be declared in the same way, separated by commas
- statement ends with a semicolon

I removed "<<annotation>>" because I don't have a clue what it means.  Is that like putting labels on stuff in VHDL? -- It doesn't do anything, semantically, it's just to keep better track of things, metadata?

[1] I tried assigning a default in a few examples, but it didn't do jack.  resetValue (which, though not mentioned, is apparently case sensitive) was required for that functionality.

I think I have a useful idea what <<direction?>>, <<register?>> and <<type>> are doing, which are also the only ones specified in that section.

I'm probably misinterpreting the use of the "*" and "?" in this definition as well.  Something about optional, or "fill in the blank here" sorts of tokens I guess?  Which I've normally seen indicated with different bracket types, which is also easier to read.  If nothing else, provide a succinct definition so the reader isn't guessing.

And then on top of that, providing an example of each form (using/not each optional token), and explaining those.  Verbose face-pounding-on-desk stuff.

Anyway, just to say, the documentation needs work.  I don't know if this was written for the game, or was only a brief summary already on the site, or even is the "comprehensive" documentation for the language itself period (god, I hope not!).

If you want a game, it has to be easy and friendly.  It's a puzzle, so leave the thinking for the solution, not for trying to figure out what to do. :-+

As for the game itself:
- The text box looks like it stays highlighted where the cursor is, when not in focus (at least, in Chrome it does).  More than a few times I've clicked "play", then started trying to edit with the keyboard, only to realize it's not in focus after all.  The button should... not take focus, or automatically return focus to the previous object, or something.  A key combo would also be handy (e.g., CTRL+ENTER, and put a note on screen showing this), since this is a rather keyboard-oriented puzzle.  TAB is used for tabbing rather than cycle focus, so, that mechanism isn't really handy.
- The "compiler" errors/warnings are fairly cryptic, mostly summed up as "RTFM".  I'll admit "RTFM" is still a little better than some of the messages I've had from, say, Quartus, but... it's a game.  It should be a hint, relevant and useful.  (Like it should on a real compiler..).  Not a terse dismissal, and certainly not a dismissal towards equally unwelcoming documentation!  Or if not everyone appreciates hints, make the hinting level selectable (like the online puzzles, like, Sudokus that have custom error checking options).  Yes, I can guess making accurate, useful, general and yet sensitive error messages isn't exactly a trivial problem, but it's always one worth spending time on.
- The "compile" kind of takes a long time.  Which might very well be justified.  I have not written an HDL parser myself, so I have no idea.  (Also, is this client side scripted?)
- The compile/notice/error message bar pushes the text box down.  This doesn't hurt anything, but it's confusing if you're working in the text box and it appears to suddenly shift.  Maybe it can be made into a static (always there, but color/text changing?) status bar?
- I like the traditional IDE style, highlighting and stuff.  Could we get, like, a toolbox to pick keywords from?  In the spirit of gaming, it would help to have an on-screen list of options, functions, statements, etc. to choose from.  Doesn't at all have to be, like, a full-on grammar creation wizard, that would be kind of giving it away too easily.  A quick visual tutorial describing the operators would also be cool ("I know I need o low when a and b are high, now, what thingy does that..?!").

Additional thoughts:
Hardware is, of course, hardly just (ideal, asynchronous) combinatorial and (ideal, no delay) sequential logic...  Timing is kinda-sorta implied by the slopey edges of the waves, but it doesn't mean anything of course, that's just for visual style.

Adding timing constraints could potentially make one hell of an awful "game" (just look at how bad it is IRL..), but if well executed, could be a refreshing "advanced" challenge perhaps.  And if that worked out well... would give you one hell of a tool to thumb in the noses of the big players.  Take that, Altera, our tool that's just a toy is as powerful as yours and orders of magnitude easier -- and fun to use!

Or, the option of using different logic drives (IEEE 1164 std. 1, 0, Z, H, L...), or a "bare bones" mode where you only get to use binary operands on bit vectors (hope you know your Karnaugh maps!), stuff like that.

Being an analog guy myself, I can't help but imagine if even a "simple" circuit version of this could be made -- say, a signal has to be within so-and-so percent (absolute, or RMS error, or frequency, or..) of the example, and you have to use resistors, capacitors, inductors, diodes, transistors and op-amps to achieve it.  Probably also in incremented skill levels, so you start with a small toolbox and go from there.  Like the old days with, The Incredible Machine (anyone remember that one?), you get some parts, few at first, then more later, then more restrictive sets even later.  Restrictions could include getting only certain component types, and of certain values.  The tools are out there; I should think this kind of functionality could be combined with something like that Falstead simulator, probably with a fair amount of work.  It would be really cool though.

...Then for the "pro" version, you combine the analog one with the PSHDL one and get a full on mixed signal puzzle game. ;D

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline daveatol

  • Regular Contributor
  • *
  • Posts: 136
  • Country: au
Re: Game of waves
« Reply #2 on: April 26, 2014, 09:09:24 am »
That was a pretty cool puzzle/game that you wrote  :clap: . The compiler error messages and manual were sufficient for me to answer all questions, but as I've never seen that language before, it would be nice to see a few more code examples in the instructions as they are easier to learn the language syntax from (for me at least).
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2051
  • Country: nl
Re: Game of waves
« Reply #3 on: April 26, 2014, 09:59:27 am »
Interesting, and nicely done. :)

The documentation needs some work though. ;) Guessing the probable syntax was faster than trying to look it up, with or without CTRL-F.
 

Offline kbeckerTopic starter

  • Contributor
  • Posts: 19
Re: Game of waves
« Reply #4 on: April 26, 2014, 07:08:05 pm »
First of all I would like to thank you for your feedback, especially T3sl4co1l, I will come to your feedback in a separate post as it will be much longer :)
Interesting, and nicely done. :)

The documentation needs some work though. ;) Guessing the probable syntax was faster than trying to look it up, with or without CTRL-F.

If you were able to guess the syntax pretty quickly, I take that as a compliment towards language design ;)
You're absolutely right regarding the documentation, I will come to that in a second.

That was a pretty cool puzzle/game that you wrote  :clap: . The compiler error messages and manual were sufficient for me to answer all questions, but as I've never seen that language before, it would be nice to see a few more code examples in the instructions as they are easier to learn the language syntax from (for me at least).

On PSHDL.org I have an examples section on which I show how to come some common constructs. I know that it is pretty popular, but I was pondering the question on how I could add those to the game without spoiling the solution too much, so I left them out for now. If you could come up with an interesting idea on how to do that, I would be very interested.

Designing good language documentation is very difficult. Some people prefer EBNF grammar styles with all side-effect documented, other prefer an example driven documentation. I kind of like the documentation from XTend (the language), so my attempt was the "learn" tab on PSHDL.org. Maybe you can take a look at those 3 (The examples, the documentation and the learn tab) and tell me which one you like best so that I can focus my energy on that.

One of the ideas I had was to create a keyword based indexed reference, which could also be used to improve the error messages. Error messages nonetheless are tremendously hard to do, but I hope that my idea with the keywords works and I will find the time to implement it soon.

One of the cool things about this game is that I can see how people are learning the language and adjust my guides to it :) This is a definite advantage to an online tool vs. the offline tools.
 

Offline kbeckerTopic starter

  • Contributor
  • Posts: 19
Re: Game of waves
« Reply #5 on: April 26, 2014, 08:12:48 pm »
Neet!

I like the idea.  I dare say it's disruptive.  You could potentially eliminate one entire year, perhaps more, from a typical EE/CE curricula branch by prescribing just a few weeks' dabbling in this thing.  (I mean, most places have those damned online math problem checker things, that never work and are always tedious to frustrating.  This isn't much different, though -- I expect -- a lot more lenient on the acceptable solution side!)

Plus if kids just randomly find this and pick up on it, maybe pair it with some cheapshit Arduino-esque things so there's even something to hold in ones' hand, you could make even more of it.

Thanks a lot! I really aim to be disruptive with PSHDL as I hate the tools as they are right now. I am actually a PhD in the fields of computer science with a specialization on FPGAs. I presented my idea at the EduCon 2014 and the feedback was pretty well, so there is a good chance that this will indeed find its way into EE/CE curricula. But of course I could need any help I can get.

Regarding the Arduino-esque PCB, I actually have a (currently not so well looking) crowd funding campaign running: https://www.indiegogo.com/projects/pshdl-board/

I assume you're interested in comments?...

One odd thing about just the first puzzle.  Not knowing the language and just guessing, my first instinct was "o = !a", which it turns out is a boolean negation.  Which isn't a bitwise negation.  I guess it implicitly casts one to the other, but the "hardware size" figure was massive, like 240-some-odd, whatever that means of course -- whereas the "~" version does indeed generate the 4 pictured.

I would like to know more about the "hardware size" number.  What actually does it represent?  Does that bear any relation to hardware that would synthesize IRL?  Is it closer to RTL level (where a latch array is roughly equivalent to an adder or multiplier block), or gate level (and what kind -- MSI/SSI, or like NAND level)?  Or neither, is it more of a software algorithmic result instead?  (Which may still be representative of the underlying logic, but in a broadly different way, of course.)

Real hardware will, of course, optimize the boolean example fully away, but will also have adders, multipliers and other macro logic available on the fabric, making certain other operations far easier than sheer logic implies (e.g., using a counting integer in "Slow me" gets... 100-200 I think it was, which really only needs a couple latches and a constant adder; versus a ripple counter, which got me 44).  Which is absolutely platform-dependent, of course -- I certainly wouldn't expect a game to simplify this sort of thing to that level!

Ok, so this will be a long trip, so stay with me :) PSHDL is generally a language that aims at FPGA programming and aims to make synchronous designs easier. The way you can make this work on any FPGA is with the VHDL export, which you can easily test on PSHDL.org. The resulting VHDL maps almost one to one, so you can re-use it if you don't want to continue PSHDL. Anyway, another aim is to make simulation behave exactly as the behavioral does. It also aims to be significantly faster and it achieves this by compiling to C/DART(JavaScript) or Java. You might be like: what? Those are sequential languages! And you're right. I divide the code in such a way that I can create a sequential model of it and then sort it topological. This way a simulation takes at most (#clk domains)+1 iterations over all combinatorial logic. You can read a bit it here: http://code.pshdl.org/pshdl.interpreter/wiki/Home

So now I have a sequential model with bit level accuracy (that is a combinatorial loop is defined on bit level, rather than variable name like with Verilator). On that model I now compute a very simplified cost. The logic is roughly: a LUT costs 4 units. Bit operations cost 1 LUT per bit. So a 32 bit XOR costs  32*4. Any addition/subtraction/compare (other than equal/non equal) costs (2*width of operand)*4, multiplication costs width*width*4 and division width*width*4*10. Additionally a multiplexer (such as an if statement) costs (width * 4).
You can see the source code for it here: http://code.pshdl.org/pshdl.interpreter/src/master/src/org/pshdl/interpreter/costs/SimpleEstimator.java?at=master

This, of course, is sometimes utterly wrong, which is why I make absolutely no guaranties about any value. But it vaguely relates to the costs that an implementation on an FPGA might cost. FPGA resource estimation is a very tough field, and a few years ago the projects results of vendor tools from the synthesis were far off from the actual implementation. Also with better software, even without changing your code, the results may improve.

The documentation... is rather terse and doesn't explain things very well.  It's completely upside-down; in trying to use the documentation with the game, I'm spending all my time at the bottom, scouring just the syntax and declarations -- the first four challenges don't even begin to require a header, import, package, module, body or any of the high level structure mentioned!
From a logical point of view it is top to bottom, but you're right, for the game itself I should probably produce a slimmed down version.

In particular, the form of an expression or statement is presented in an unfamiliar way; this looks like a mess:
Quote
«annotation*» «direction?» «register?» «type»
   «annotation*» id [«dimension»]* (= «defaultValue»)?
   (, «annotation*» id [«dimension»]* (= «defaultValue»)?)*;
I've not seen the guillemets used before; from what I can tell, I would normally write this with a more diverse selection of braces:
Quote
[in|out|inout|param|const] [register] {type} <name>[<arraysize>] [= <defaultvalue>] [, <name2>[<arraysize>][= <defaultvalue>] [, ...]];

Where:
- square brackets [] denote an optional item,
- curly braces {} denote a required item,
- items separated by | means, pick just one
- angle brackets <> denote a required, user-defined parameter (e.g., a name for a variable)

- [in|out|inout|param|const] is the direction or visibility of the variable (and the items are...)
- [register] is a keyword which, if used, denotes a registered (persistent/state/memory/latch type) variable
- {type} is the type to declare the variable as; the primitive types are (so and so...; or list them in the braces), and <hyperlink> about libraries and stuff
- <name> is the name of the variable to declare
- [<arraysize>] is an optional parameter to specify an array type variable; use square brackets e.g., the name looks like "myarray[31]"
- [= <defaultvalue>] is the default (initial? resetted?) value of the variable[1]
- additional variables of the same {type} can be declared in the same way, separated by commas
- statement ends with a semicolon
I actually tried to write the documentation the way you described, but then I realized that using characters that are in the language itself, like []{} and <> can become very confusing. Especially when you look at the array size example of yours, or the width of the type. So I decided to use those strange arrows, because they definitely are not in the language itself. But you are right, the meaning should be documented itself.

I removed "<<annotation>>" because I don't have a clue what it means.  Is that like putting labels on stuff in VHDL? -- It doesn't do anything, semantically, it's just to keep better track of things, metadata?
Annotations are used to give the compiler a hint. For example you can say:
Code: [Select]
in bit @clock myClock; //can now be accessed with $clk and will be used by registers which don't have an explicit clock
[1] I tried assigning a default in a few examples, but it didn't do jack.  resetValue (which, though not mentioned, is apparently case sensitive) was required for that functionality.
The default value is actually equivalent to inserting a single assignment to that variable at the very top of the code (before anything else is written to it). For example:
Code: [Select]
register uint<8> counter=counter+1;
counter=0;
Is equivalent to:
Code: [Select]
register uint<8> counter;
counter=counter+1;
counter=0;
Which of course is not a counter at all, it will remain 0 at all times.

I think I have a useful idea what <<direction?>>, <<register?>> and <<type>> are doing, which are also the only ones specified in that section.

I'm probably misinterpreting the use of the "*" and "?" in this definition as well.  Something about optional, or "fill in the blank here" sorts of tokens I guess?  Which I've normally seen indicated with different bracket types, which is also easier to read.  If nothing else, provide a succinct definition so the reader isn't guessing.

And then on top of that, providing an example of each form (using/not each optional token), and explaining those.  Verbose face-pounding-on-desk stuff.
Thanks, I will take a closer look at those in the re-written documentation.

Anyway, just to say, the documentation needs work.  I don't know if this was written for the game, or was only a brief summary already on the site, or even is the "comprehensive" documentation for the language itself period (god, I hope not!).

Unfortunately I have to admit that this is the "comprehensive" documentation for the language right now. I meant to re-write that a long time ago, but didn't... :(

If you want a game, it has to be easy and friendly.  It's a puzzle, so leave the thinking for the solution, not for trying to figure out what to do. :-+
Part of the difficulty is that you need to learn the language to solve the problem, it is not a known language (yet). But I have to say that I am surprised by how well some people are picking it up and what awesome/scary/crazy solutions they come up with.

As for the game itself:
- The text box looks like it stays highlighted where the cursor is, when not in focus (at least, in Chrome it does).  More than a few times I've clicked "play", then started trying to edit with the keyboard, only to realize it's not in focus after all.  The button should... not take focus, or automatically return focus to the previous object, or something.  A key combo would also be handy (e.g., CTRL+ENTER, and put a note on screen showing this), since this is a rather keyboard-oriented puzzle.  TAB is used for tabbing rather than cycle focus, so, that mechanism isn't really handy.
Ok, noted, that should be easy to fix
- The "compiler" errors/warnings are fairly cryptic, mostly summed up as "RTFM".  I'll admit "RTFM" is still a little better than some of the messages I've had from, say, Quartus, but... it's a game.  It should be a hint, relevant and useful.  (Like it should on a real compiler..).  Not a terse dismissal, and certainly not a dismissal towards equally unwelcoming documentation!  Or if not everyone appreciates hints, make the hinting level selectable (like the online puzzles, like, Sudokus that have custom error checking options).  Yes, I can guess making accurate, useful, general and yet sensitive error messages isn't exactly a trivial problem, but it's always one worth spending time on.
Writing meaningful error messages is extraordinarily difficult as you need to assume that the user does not know the language well enough to understand what he was actually doing. I am always seeking to improve those messages, but for that I need to understand how people interpret the message. On the server side I can actually take a look at what error message has been presented and what action the user took to fix the problem. Some messages were improved upon those analysis, but I am just a single person right now, so I have to focus my energy.
- The "compile" kind of takes a long time.  Which might very well be justified.  I have not written an HDL parser myself, so I have no idea.  (Also, is this client side scripted?)
If it took more than 100ms my server was probably busy. In the world of HDL parsing/validation/simulation this is insanely fast. Most tools take that amount of time to show a splash screen.
- The compile/notice/error message bar pushes the text box down.  This doesn't hurt anything, but it's confusing if you're working in the text box and it appears to suddenly shift.  Maybe it can be made into a static (always there, but color/text changing?) status bar?
I will take further into that
- I like the traditional IDE style, highlighting and stuff.  Could we get, like, a toolbox to pick keywords from?  In the spirit of gaming, it would help to have an on-screen list of options, functions, statements, etc. to choose from.  Doesn't at all have to be, like, a full-on grammar creation wizard, that would be kind of giving it away too easily.  A quick visual tutorial describing the operators would also be cool ("I know I need o low when a and b are high, now, what thingy does that..?!").
Those editors are called projected editors. I have chosen to use a regular approach to editing, this would be really really difficult to implement.

Additional thoughts:
Hardware is, of course, hardly just (ideal, asynchronous) combinatorial and (ideal, no delay) sequential logic...  Timing is kinda-sorta implied by the slopey edges of the waves, but it doesn't mean anything of course, that's just for visual style.

Adding timing constraints could potentially make one hell of an awful "game" (just look at how bad it is IRL..), but if well executed, could be a refreshing "advanced" challenge perhaps.  And if that worked out well... would give you one hell of a tool to thumb in the noses of the big players.  Take that, Altera, our tool that's just a toy is as powerful as yours and orders of magnitude easier -- and fun to use!
The simulation that I have right now could be extended to do that, but right now I have no intentions of doing that. Doing timing right requires a timing model, which requires the vendor tools as with a proper resource estimation. I don't want to do that.

Or, the option of using different logic drives (IEEE 1164 std. 1, 0, Z, H, L...), or a "bare bones" mode where you only get to use binary operands on bit vectors (hope you know your Karnaugh maps!), stuff like that.
PSHDL is binary only (with a hack to create highZ for I2C or alike on output ports). This is because, that is the reality of FPGAs, only 1 or 0 exists. High-Z is mapped to a complex bus system if used internally.
Being an analog guy myself, I can't help but imagine if even a "simple" circuit version of this could be made -- say, a signal has to be within so-and-so percent (absolute, or RMS error, or frequency, or..) of the example, and you have to use resistors, capacitors, inductors, diodes, transistors and op-amps to achieve it.  Probably also in incremented skill levels, so you start with a small toolbox and go from there.  Like the old days with, The Incredible Machine (anyone remember that one?), you get some parts, few at first, then more later, then more restrictive sets even later.  Restrictions could include getting only certain component types, and of certain values.  The tools are out there; I should think this kind of functionality could be combined with something like that Falstead simulator, probably with a fair amount of work.  It would be really cool though.
I would love to see that! I am, unfortunately, not so good at analog design, so having something like this would be very interesting for me.
...Then for the "pro" version, you combine the analog one with the PSHDL one and get a full on mixed signal puzzle game. ;D

Tim
If you write the analog simulator, I will help you with the mixed signal thingy :) Thinking about it, it should be too hard to write a PSpice binary plugin... Hmmmm ;)

Thanks a ton for your feedback Tim, I will take a look into some of the points that you mentioned and hopefully improve on those.

Karsten
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Game of waves
« Reply #6 on: April 26, 2014, 09:19:30 pm »
Thanks a lot! I really aim to be disruptive with PSHDL as I hate the tools as they are right now. I am actually a PhD in the fields of computer science with a specialization on FPGAs. I presented my idea at the EduCon 2014 and the feedback was pretty well, so there is a good chance that this will indeed find its way into EE/CE curricula. But of course I could need any help I can get.

Karsten

What I'm waiting for is a good Erlang toolchain for FPGAs, Altera's OpenCL efforts are good too.

There is a surging need for high level functional programming languages to take advantage not only of FPGAs but also because of the rapid increase of multicore processors.

I did play with your Game, and I do like the approach.
I also like the declaration and instantiation for external VHDL or Verilog code.

For example if you are going to use Verilog on VHDL you will have to do something like this:
Code: [Select]
--  // hdmi_controller
    component hdmi_controller is
    port
    (
        iRST_n : in std_logic;
        iVGA_CLK : in std_logic;
        oBLANK_n : out std_logic;
        oHS : out std_logic;
        oVS : out std_logic;
        b_data : out  std_logic_vector(7 DOWNTO 0);
        g_data : out  std_logic_vector(7 DOWNTO 0);
        r_data : out  std_logic_vector(7 DOWNTO 0)
    );
    end component hdmi_controller;

...

--  // hdmi_controller
    GEN_hdmi_controller : if not PACE_HAS_PLL generate
    hdmi_controller_inst : hdmi_controller
    port map
    (
        iRST_n => dly_RST,
        iVGA_CLK => disp_clk,
        oBLANK_n => hdmi_out_de,
        oHS => hdmi_out_hsync,
        oVS => hdmi_out_vsync,
        b_data => hdmi_out_blue,
        g_data => hdmi_out_green,
        r_data => hdmi_out_red
    );
    end generate GEN_hdmi_controller;
Then use it.
Code: [Select]
   ...
    hdmi_out_red <= video_o.rgb.r(9 downto 2);
    hdmi_out_green <= video_o.rgb.g(9 downto 2);
    hdmi_out_blue <= video_o.rgb.b(9 downto 2);
    hdmi_out_hsync <= video_o.hsync;
    hdmi_out_vsync <= video_o.vsync;
    hdmi_out_de <= not (video_o.hblank or video_o.vblank);

In PSHDL it seems I would only need to declare the interface.
Code: [Select]
interface Verilog.work.hdmi_controller {
    in bit iRST_n
    in bit iVGA_CLK;
    out bit oBLANK_n;
    out bit oHS;
    out bit oVS;
    out bit<8> b_data;
    out bit<8> g_data;
    out bit<8> r_data;
}
Then use it in the code with, hmmm it seems I got it backwards and outputs are inputs, or what am I missing?

This code won't do what I want, I have to reverse them right?
Code: [Select]
    import Verilog.work.*;
    hdmi_controller hdmi_c;
    hdmi_c.iRST_n=$rst;
    hdmi_c.iVGA_CLK=$clk;
    out bit blank = hdmi_c.oBLANK_n;
    out bit hs = hdmi_c.oHS;
    out bit vs = hdmi_c.oVS;
    out bit<8> blue = hdmi_c.b_data;
    out bit<8> green = hdmi_c.g_data;
    out bit<8> red = hdmi_c.r_data;

also, do the vectors need to be?
    out bit<8> blue = hdmi_c.b_data{7:0};

But I have not look at a lot of details on PSHDL
 

Offline kbeckerTopic starter

  • Contributor
  • Posts: 19
Re: Game of waves
« Reply #7 on: April 26, 2014, 10:44:31 pm »
What I'm waiting for is a good Erlang toolchain for FPGAs, Altera's OpenCL efforts are good too.

I personally think that OpenCL is a by far better idea than regular C(++) or SystemC HLS. But PSHDL is still more of an assembler from the logical level, even though it does have some code generation features that essentially allow to embed other languages into it. In a not so distant future I will support TransC http://cgi.tu-harburg.de/~ti6hm/ and Hierarchical State machines http://blog.pshdl.org/2014/04/the-future-of-pshdl-part-2-modules-and.html. If you enjoy Java, you can certainly use it to build code. It took me about a day to add a sequential language output like C/Java or Dart, so I guess adding Erlang would not take much longer.

There is a surging need for high level functional programming languages to take advantage not only of FPGAs but also because of the rapid increase of multicore processors.

I have a student investigating OpenCL multithreading for simulation of PSHDL. While the execution on the GPU looks not very promising, there is a good potential to use OpenCL for multithreading on the CPU. Something that most hardware simulators are still not able to do properly.

I did play with your Game, and I do like the approach.
I also like the declaration and instantiation for external VHDL or Verilog code.

For example if you are going to use Verilog on VHDL you will have to do something like this:
....

In PSHDL it seems I would only need to declare the interface.
Code: [Select]
interface Verilog.work.hdmi_controller {
    in bit iRST_n
    in bit iVGA_CLK;
    out bit oBLANK_n;
    out bit oHS;
    out bit oVS;
    out bit<8> b_data;
    out bit<8> g_data;
    out bit<8> r_data;
}
Then use it in the code with, hmmm it seems I got it backwards and outputs are inputs, or what am I missing?

This code won't do what I want, I have to reverse them right?
Code: [Select]
    import Verilog.work.*;
    hdmi_controller hdmi_c;
    hdmi_c.iRST_n=$rst;
    hdmi_c.iVGA_CLK=$clk;
    out bit blank = hdmi_c.oBLANK_n;
    out bit hs = hdmi_c.oHS;
    out bit vs = hdmi_c.oVS;
    out bit<8> blue = hdmi_c.b_data;
    out bit<8> green = hdmi_c.g_data;
    out bit<8> red = hdmi_c.r_data;
It looks correct to me. The interface declares it as you would declare it in a VHDL component declaration.

also, do the vectors need to be?
    out bit<8> blue = hdmi_c.b_data{7:0};

But I have not look at a lot of details on PSHDL
If you use all bits from a variable, you don't need to specify the bits that you plan to access. For VHDL files you don't actually have to declare the interface if you have the VHDL file in your workspace. If I can find a suitable Verilog parser for Java, I might add this for Verilog as well.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Game of waves
« Reply #8 on: April 26, 2014, 10:56:14 pm »
wouldn't I also need to do the following?
Code: [Select]
    red = video_o.rgb.r{9:2};
    green = video_o.rgb.g{9:2};
    blue = video_o.rgb.b{9:2};
    hs = video_o.hsync;
    vs = video_o.vsync;
    blank = ~ (video_o.hblank | video_o.vblank);

That's what I meant not doing what I want directly, so I still end up declaring and generating the instance but I still have to use it right?
 

Offline kbeckerTopic starter

  • Contributor
  • Posts: 19
Re: Game of waves
« Reply #9 on: April 26, 2014, 11:02:07 pm »
Hmm, guess I have an idea of what you mean now. You can combine the declaration and assignment:
Code: [Select]
    out bit<8> red = video_o.rgb.r{9:2};
    out bit<8> green = video_o.rgb.g{9:2};
    out bit<8> blue = video_o.rgb.b{9:2};
    out bit hs = video_o.hsync;
    out bit vs = video_o.vsync;
    out bit blank = ~ (video_o.hblank | video_o.vblank);

That's what I meant not doing what I want directly, so I still end up declaring and generating the instance but I still have to use it right?

Well using the instance makes sense ;) (I guess I am not entirely sure what you mean, but maybe the code answered the question)

In VHDL you usually have to declare an intermediate signal because some (most) expressions are not allowed in the port mapping. In PSHDL you don't have that restriction.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Game of waves
« Reply #10 on: April 26, 2014, 11:18:15 pm »
Hmm, guess I have an idea of what you mean now. You can combine the declaration and assignment:
Code: [Select]
    out bit<8> red = video_o.rgb.r{9:2};
    out bit<8> green = video_o.rgb.g{9:2};
    out bit<8> blue = video_o.rgb.b{9:2};
    out bit hs = video_o.hsync;
    out bit vs = video_o.vsync;
    out bit blank = ~ (video_o.hblank | video_o.vblank);

Well using the instance makes sense ;) (I guess I am not entirely sure what you mean, but maybe the code answered the question)

In VHDL you usually have to declare an intermediate signal because some (most) expressions are not allowed in the port mapping. In PSHDL you don't have that restriction.

But then it doesn't use the interface, I think I'm missing something.

How does it know to call my Verilog (or VHDL) module that takes care of all the timings etc?
 

Offline kbeckerTopic starter

  • Contributor
  • Posts: 19
Re: Game of waves
« Reply #11 on: April 26, 2014, 11:42:08 pm »
I think we're misunderstanding each other here :) So let me try to make a full source code here:
Code: [Select]
interface VHDL.work.hdmi_controller {
    in bit iRST_n
    in bit iVGA_CLK;
    out bit oBLANK_n;
    out bit oHS;
    out bit oVS;
    out bit<8> b_data;
    out bit<8> g_data;
    out bit<8> r_data;
}
module myPSHDLModule {
    import VHDL.work.*;
    hdmi_controller hdmi_c;
    hdmi_c.iRST_n=$rst;
    hdmi_c.iVGA_CLK=$clk;
    out bit<8> red = video_o.rgb.r{9:2};
    out bit<8> green = video_o.rgb.g{9:2};
    out bit<8> blue = video_o.rgb.b{9:2};
    out bit hs = video_o.hsync;
    out bit vs = video_o.vsync;
    out bit blank = ~ (video_o.hblank | video_o.vblank);
...
}

You declare the interface, and then you use it. It will then assume that during synthesis someone provides the hdmi_controller net-list and is somehow compatible with the declared interface (as it is the case with components in VHDL). (Verilog.work is not (yet) a good name. VHDL.work.X will be translated to X, which is expected to live in work, whereas Verilog.work.X will be translated to work_x that is expected to exist in a library verilog. PSHDL doesn't care about the name itself, it is the VHDL output that cares about it. I have to admit that this may be confusing, so I will think about it :))
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf