Game of waves - Page 1
Forum section: electronics / general

author: kbecker
author_rank: Contributor
timestamp: April 26, 2014, 03:41:36 am
content: Hey everyone,When I was working on a new API for interactive tutorials I realized that I could create a little game, which I didYou can check it out athttp://waves.pshdl.orgKarsten

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 26, 2014, 08:11:47 am
content: 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:QuoteI've not seen the guillemets used before; from what I can tell, I would normally write this with a more diverse selection of braces:QuoteI 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? 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.Tim

author: daveatol
author_rank: Regular Contributor
timestamp: April 26, 2014, 09:09:24 am
content: That was a pretty cool puzzle/game that you wrote. 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).

author: mrflibble
author_rank: Super Contributor
timestamp: April 26, 2014, 09:59:27 am
content: 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.

author: kbecker
author_rank: Contributor
timestamp: April 26, 2014, 07:08:05 pm
content: 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 longerQuote from: mrflibble on April 26, 2014, 09:59:27 amIf you were able to guess the syntax pretty quickly, I take that as a compliment towards language designYou're absolutely right regarding the documentation, I will come to that in a second.Quote from: daveatol on April 26, 2014, 09:09:24 amOn 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 itThis is a definite advantage to an online tool vs. the offline tools.

author: kbecker
author_rank: Contributor
timestamp: April 26, 2014, 08:12:48 pm
content: Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amThanks 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/Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amOk, so this will be a long trip, so stay with mePSHDL 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/HomeSo 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=masterThis, 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amFrom 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amI 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amAnnotations are used to give the compiler a hint. For example you can say:Code:in bit @clock myClock; //can now be accessed with $clk and will be used by registers which don't have an explicit clockQuote from: T3sl4co1l on April 26, 2014, 08:11:47 amThe 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:register uint<8> counter=counter+1;counter=0;Is equivalent to:Code: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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amThanks, I will take a closer look at those in the re-written documentation.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amUnfortunately 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...Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amPart 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amOk, noted, that should be easy to fixQuote from: T3sl4co1l on April 26, 2014, 08:11:47 amWriting 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amIf 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amI will take further into thatQuote from: T3sl4co1l on April 26, 2014, 08:11:47 amThose editors are called projected editors. I have chosen to use a regular approach to editing, this would be really really difficult to implement.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amThe 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amPSHDL 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amI 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.Quote from: T3sl4co1l on April 26, 2014, 08:11:47 amIf you write the analog simulator, I will help you with the mixed signal thingyThinking about it, it should be too hard to write a PSpice binary plugin... HmmmmThanks 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

author: miguelvp
author_rank: Super Contributor
timestamp: April 26, 2014, 09:19:30 pm
content: Quote from: kbecker on April 26, 2014, 08:12:48 pmWhat 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:-- // hdmi_controllercomponent hdmi_controller isport(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_controllerGEN_hdmi_controller : if not PACE_HAS_PLL generatehdmi_controller_inst : hdmi_controllerport 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:...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:interface Verilog.work.hdmi_controller {in bit iRST_nin 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: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

author: kbecker
author_rank: Contributor
timestamp: April 26, 2014, 10:44:31 pm
content: Quote from: miguelvp on April 26, 2014, 09:19:30 pmI 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 TransChttp://cgi.tu-harburg.de/~ti6hm/and Hierarchical State machineshttp://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.Quote from: miguelvp on April 26, 2014, 09:19:30 pmI 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.Quote from: miguelvp on April 26, 2014, 09:19:30 pmIt looks correct to me. The interface declares it as you would declare it in a VHDL component declaration.Quote from: miguelvp on April 26, 2014, 09:19:30 pmIf 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.

author: miguelvp
author_rank: Super Contributor
timestamp: April 26, 2014, 10:56:14 pm
content: wouldn't I also need to do the following?Code: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?

author: kbecker
author_rank: Contributor
timestamp: April 26, 2014, 11:02:07 pm
content: Hmm, guess I have an idea of what you mean now. You can combine the declaration and assignment:Code: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);Quote from: miguelvp on April 26, 2014, 10:56:14 pmWell 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.

author: miguelvp
author_rank: Super Contributor
timestamp: April 26, 2014, 11:18:15 pm
content: Quote from: kbecker on April 26, 2014, 11:02:07 pmBut 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?

author: kbecker
author_rank: Contributor
timestamp: April 26, 2014, 11:42:08 pm
content: I think we're misunderstanding each other hereSo let me try to make a full source code here:Code:interface VHDL.work.hdmi_controller {in bit iRST_nin 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)