Hacker News new | past | comments | ask | show | jobs | submit login
Lisp CPU (frank-buss.de)
180 points by auvi on June 24, 2014 | hide | past | favorite | 67 comments



This would be interesting, but it looks like it has been barely started - the CPU is barely what I would call a CPU, let alone a Lisp interpreter.

Verilog isn't a programming language (it tries to be, unfortunately). For synthesis, it is a hardware description language. Someday I'll write up some decent Verilog tutorials because there aren't any good ones on the Internet.


My thoughts exactly. When I saw "Perhaps the Verilog language is not so good, because some nice standard language featuers (forever-loop etc.) are missing in the Xilinx-Tools.", I had flashbacks to VHDL class, students writing loops and then wondering why they couldn't synthesize the code. You have to get yourself into a hardware mindset, thinking about clocks and state machines and enable lines rather than infinite loops.


Yeah, it looks like this guy needs to learn more Verilog before he can make progress on the CPU implementation.

It reminds of teaching some VHDL in a hackerspace a few years ago (I had learned it in college some years previously), and this software guy was constantly trying to write functions and loops, and was having trouble with the concept that all signals were propagated concurrently rather than sequentially!

Sure, it looks like code (in fact, VHDL's syntax is purposefully similar to ADA), but it sure isn't code.


this guy needs to learn more Verilog

That's not a bad thing.

Maybe this is why a Lisp processor doesn't exist. Not only do you have to know Lisp well, which only a minority of programmers do, but you also need to want to know hardware. Which is something software people don't want to do. This guy already has a leg up.

For some strange reason I can't explain it's easier to imagine a software guy building hardware than a hardware guy writing a Lisp.


That seems odd when you consider that a Lisp can be implemented in, what, a couple hundred lines of C? All the guys who can design a processor know how to program, and it's not like Lisp is totally magical.

Now, most people who do primarily hardware work probably aren't that interested in Lisp, because there's not really much Lisp focus out there. I'm a computer engineer, I know how to write HDL and lay silicon, I like Lisp... actually it would be a pretty fun project to do in an FPGA.


They know how to program. Do they know what to program?


It's funny, because in some cases you can write HDL code that looks like a loop - but in this context a loop instantiates multiple instances of some piece of logic.


Exactly.

And this kind of distinction was what we were having trouble conveying to said software guy (I say this as a software guy myself), and I think the author of the LISP CPU is having the same problem.


I think I'd explain that particular bit by simply saying that there was no run-time looping construct, only a compile-time looping macro to generate runtime code. Most software people would get that, I think.


If you teach Verilog without explaining why it has loops and what they do (and don't do), you don't teach it correctly.

Behavioral descriptions are very, very similar to programming, and a lot of programming concepts and skills (e.g. modularization) translate very well to HDLs.

The only thing in HDLs I remember that is totally alien to programmers is propagation delays. Well, even that is somewhat similar to multi-threading issues.


> this software guy was constantly trying to write functions and loops, and was having trouble with the concept that all signals were propagated concurrently rather than sequentially!

Sounds like he hadn't written much software in a language with an actor-model. It's not nearly as hard a jump to VHDL if you've ever debugged an Erlang supervision tree, or a miscommunicating set of SOA web services.


Would it be fair to describe it as concurrently executed code?


hah, that's only the tip of the iceberg...

From memory:

- HDL code doesn't have variables the way programming code does. Sure, you can store state in latches (and other more roundabout ways), but a good design tries to avoid this.

- You can have "functions" that take parameters, but what you're really doing is instantiating blocks of hardware according to said parameters.

- Instead of variables to functions, what you really care about is signals as input and output to hardware blocks. (and ultimately at the final hardware implementation, propagation time and power of said signals. Especially the clock. OMG the clock...)

Honestly, I found VHDL made complete sense from approaching it after drawing digital circuit diagrams, as the description code mapped pretty clearly to that. Approaching it from an "imperative programming" background makes little sense, and saying it's "concurrent programming" just ends up confusing the issue more, IMHO.


Absolutely agree with learning digital circuit design first. Before writing a single line of HDL, you should know exactly what you want to be synthesized.

Unfortunately all to many courses approach like learning a new programming language. To me this is like teaching CAD before teaching how to draw a rectangle.


It's more like wiring together a series of tubes. The signal has to propagate from one end of the tubes to the other in a single clock cycle. Note that the tubes can go backwards, so you can feed the output of the tube into the next input of itself. Hardware programming like this is actually extremely fun, but for some reason the widely available languages for doing it suck. And make what is going on in the hardware opaque and difficult to understand for any non trivial applications. (We're talking 100000s of lines of code to do anything nontrivial).


I think you could. Contrary to most comments on this page, I do think that you should be able to write high-level code with "if" and "while" and have the compiler generate the hardware for you. Actually, that's what we (Synflow) are doing with our language. So you don't have to spend so much time learning Verilog/VHDL and typing all those Finite State Machines and scheduling next state processes and so on. Take a look at our website www.synflow.com and let us know what you think!


Sure, it looks like code (in fact, VHDL's syntax is purposefully similar to ADA), but it sure isn't code.

Computer science grad here. I had to keep reminding myself about the HDL part of VHDL. It's not algorithmic description like programming is, but hardware description.



I took a look and I don't know where to start. The table of content is completely different from how I would introduce the concepts. The site says "This book requires that you first read Digital Circuits", which is a good point, so maybe most of the design/Verilog content should go there instead.

Unfortunately, the digital circuit book also doesn't have a modern table of content: SR flip-flops and 7400TLS are not exactly related to Verilog much at all.

Is there a place where such issues can be discussed?

EDIT: I started https://en.wikibooks.org/wiki/Programmable_Logic/Verilog_for...


Both "books" are kind of regrettable, but SR flip-flops and 7400-type logic gates are essential background knowledge for writing HDL. You'll have a hard time describing hardware if you don't know what kind of hardware you're trying to describe... Verilog looks vaguely C-ish, but in the end you're describing how to connect up a bunch of flip-flops and logic gates.


In modern digital hardware design, you only use D flip-flops (with some very rare exceptions), so teaching SR, JK etc. is not only unnecessary, but also confusing to beginners. Showing how to build them from gates is even worse, because it's typically wrong and results in a level-triggered latch (which you don't use in modern digital hardware design).

You don't build more complex functions like adders or multiplexers from individual gates anymore, so don't put beginners into this outdated mindset. Sure, explain how to build a half-adder from ANDs and XORs, but make it clear that they shouldn't do this for anything except experimentation; you don't need any specific parts like the 7400s for this. Instead, teach them proper design techniques with HDLs (as horrible as VHDL and Verilog are, they are better than schematic designs).


Well, when I did VLSI, I built adders from individual gates... but I only took one course in VLSI, so maybe I'm wrong.


Let me know when you do so, I can help.


Please do! I've wanted to learn FPGAs for years now, never really got around to it because it's really so niche there's not that much quality tutorials.


Just let us know when you have writen some tutorials - Im waiting :)


You need to look at The Architecture of Symbolic Machines by Peter Kogge. It contains a machine you can implement. I have implemented it in the Jatha LISP interpreter ( http://sourceforge.net/projects/jatha/ ).


I'd like to point out that the code he has on there isn't a Lisp CPU and I don't think will even work in a real FPGA. I don't know Verilog, just VHDL, but that business in the INIT state looks sketchy to say the least. Even if it does work, it just loads a few instructions into memory & executes them; these instructions blink an LED on the board. The Lisp architecture is barely described beyond a few sparse notes about a tagged memory arch (not implemented).

I'm not attacking the original author; these look like personal notes as he explores an FPGA and realizes that hardware design is complicated. But don't get your hopes up on this being... well, anything.


yeah it's definitely not synthesizable in its current state, not to mention that he's going to have a bad time if he messes with the clock the way he does in this code (the way he generates his slowClock, unless his tools are clever enough to recognize this pattern and do the right thing).

It's a cool project though, but if I were him I'd learn the language with some simpler and smaller designs, maybe some stuff he'll be able to re-use in his final CPU.

As it is it reads a bit like someone who wants to write a kernel in C while not understanding how pointers work.


This was started back in 2004 and the last update was in 2007 apparently [1], not a lot of the content changed. Building CPUs in FPGAs is fun, a lot of the demo boards available these days already have memory and often either an SD card type interface or some sort of NAND flash attached. A good place to start if your interested is fpgacpu.org ( not exactly a 'live' site but there is good info in there ) or opencores.org.

[1] http://web.archive.org/web/*/http://www.frank-buss.de/lispcp...


These more recent projects also made Lisp machines in FPGAs. It looks like they got further than the original post here:

LispmFPGA (2008) http://www.aviduratas.de/lisp/lispmfpga/

https://groups.google.com/forum/?fromgroups=#!topic/comp.lan...

IGOR (2008) http://opencores.org/project,igor

https://www.flickr.com/photos/kaitorge/sets/7215760944571932...


I'd like to see a modern CPU that handles dynamic typing in hardware. Registers can store values as well as the type, e.g. 32 value bits and a few type bits. Basic arithmetic like addition can automatically compare the type bits and just do the right thing with a single instruction (fixnum add, float add, bignum add, etc.).

Would this be cool or am I dreaming?


Not quite dynamic typing, but the Mill CPU stores a lot of metadata in-CPU (which is lost when written to memory)- things like size, vector width, validity of the value (as opposed to faulting immediately) or ALU status bits (overflow, zero). The particular interpretation of the bits is still left up to the opcode used, but it does enable some neat tricks that vaguely remind me of dynamic typing.

http://millcomputing.com/topic/metadata/


That reminds me SOAR[1] (from 1984): Smalltalk on a RISC

Smalltalk on a RISC (SOAR) is a simple, Von Neumann computer that is designed to execute the Smalltalk-80 system much faster than existing VLSI microcomputers. The Smalltalk-80 system is a highly productive programming environment but poses tough challenges for implementors: dynamic data typing, a high level instruction set, frequent and expensive procedure calls, and object-oriented storage management. SOAR compiles programs to a low level, efficient instruction set. Parallel tag checks permit high performance for the simple common cases and cause traps to software routines for the complex cases. Parallel register initialization and multiple on-chip register windows speed procedure calls. Sophisticated software techniques relieve the hardware of the burden of managing objects. We have initial evaluations of the effectiveness of the SOAR architecture by compiling and simulating benchmarks, and will prove SOAR's feasibility by fabricating a 35,000-transistor SOAR chip. These early results suggest that a Reduced Instruction Set Computer can provide high performance in an exploratory programming environment.

[1] http://dl.acm.org/citation.cfm?id=808182


I'm pretty sure it was already done in the Symbolics Lisp Machine.


Also in the LMI K-machine [1].

I got part way through building type checking hardware to use with Franz Lisp on 68k CPUs. Franz Lisp allocated objects of a single type in each page and the 68k had function code pins that meant you could tell whether a bus read was for data or instruction fetch, the idea was that I would modify the compiler to read a latched type value just after a Lisp object had been read into a register.

[1] http://fare.tunes.org/tmp/emergent/kmachine.htm


As I recall (and I may have some of this wrong) the Symbolics 3600 machines used a few extra bits to tag types like 32bit_int, 32bit_float, and pointer_to_object. And when operating on integers, the cpu would assume it had 32bit_ints and would raise a low-level signal to interrupt the operation if the operands were something else (like bignums).

There were also extra bits in each word for cdr-coding lists, which was a way to internally implement a list as an array.

There might have also been an extra bit for GC, maybe for mark-and-sweep.


Yet again in the Lisp world, the past is more futuristic than the present.


You may be interested in this article: "Tagged architecture: How compelling are its advantages?", http://dl.acm.org/citation.cfm?doid=327070.327153 (unfortunately behind a paywall).


Dynamic typing in hardware seems like one of the best kept secrets. It's probably easier for a software guy to think of adding dynamic typing in hardware than it does a hardware guy to want to program in a dynamic language.


There is support for tagged arithmetic in 32-bit SPARC CPUs.


It sounds feasible, but I believe you would also have to augment data values in memory with this type. Every 32 bits in memory would also need a few bits associated with it for type and the memory buses would need to be widened to move these around.


You could instead have the tag bits inside the values in memory. Have the CPU treat the data in memory as though it was 60 bits wide with 4 additional tag bits instead of 64, or something along those lines. With special instructions that ignored tag metadata for those cases where you needed the full width (mainly interoperability).


I've spoken personally to VM implementers, and yes, it would be very cool and useful besides, and yes, you are still perhaps dreaming.


Wouldn't a "Lisp CPU" be like the one in the classic Lisp Machines, which didn't execute Lisp directly, but were optimised for executing it?


The ideas on the web page are closer to the Scheme-79 chip [1] than a Lisp Machine.

[1] http://dspace.mit.edu/handle/1721.1/6334


I am not an expert, but I am definitely thinking the same thing.


Jeff's LispMicrocontroller is another example of this sort of thing (but a bit further along, it seems): https://github.com/jbush001/LispMicrocontroller


This looks like a really fun project. I'd be interested in any good Verilog resources anyone can recommend. Also, does anyone know if there is there an affordable way to get components you design manufactured on a small scale? (Not in the thousands of units, I mean.)


FPGAs are definitely the way to go. They are cheap and reprogrammable. One awesome devboard is the Zedboard. It includes 2 (?) ARM cores and a 28nm FPGA.


I'm not familiar with Verilog. I wonder if something like this[1] would be a useful tool in this developer's belt.

1: http://www.cs.colby.edu/djskrien/CPUSim/


What are the good convenient and modern FPGA's good for a modern computer?

I'm not sure what I'm asking here, really. I would ask for a PCE-Express board, but I've switched to a laptop as my main machine, with external monitor, keyboard and mouse when in home/office. I guess a PCE-Express board that could in principle be used in a rack-mount server would be useful.


Probably a Zedboard.


I don't see a PCI-Express one. Alternatively, which one do you find convenient? I think the external board should have some kind of case so that I won't have to worry about short-circuiting it.


When you say you want a PCIe one, do you really want to start by writing your own PCI slave? It's a bit of a pain. And having the FPGA on the PCI bus lets it crash your development PC when you get it wrong.


You're right, I wouldn't want to write my own PCI slave and have it crash my PC. Unless the board developer already took care of that, it's probably better to go with standalone board for now. I hope we'll see more convenient FPGA development boards that will be no more hassle to use than an extra videocard in your PC now, as Moore's law hits the wall and FPGA's become more ubiquitous.


As written, that INIT section is really going to limit clock speed. I also don't understand why currentState is double clocked.


It's not going to limit clock speed, its just not going to work. To write multiple values to different ram locations (considering a ram has at most two ports) would require you to stay in the INIT state for 9 cycles and do something like:

  INIT:
    begin
    if (count == 9) begin
      next_count == 0;
      nextState = `EVALUATE;
    end
    else 
      next_count == count + 1;
    case (count)
      0: begin ram_wr_addr = count; ram_wr_data = `CMD_LED_ON; ram_wr_en = 1; end
      1: begin ram_wr_addr = count; ram_wr_data = `CMD_LOAD_NEXT_TO_ACCU; ram_wr_en = 1; end
      etc....
    end
usually you have a ram module that takes an address and some write_data, wr_en, etc rather than accessing the array directly.


I think we've come back to "original author doesn't actually know how to write logic, thinks he's writing sequential code" as the core problem


Using double-edge clocking usually comes from a misunderstanding about how FPGA timing works. When you look at a waveform in a simulator, it's intuitive to think that you would need to change states at opposite edges to guarantee setup time. The synthesis tools will actually guarantee that setup times are met even if you use the same clock edge, though.

Also, the use of a clock divider in this way is bad practice and another trap for beginners. Use clock that are on global clock lines, and use a clock enable to slow things down.


It always surprises me to see these sorts of projects NOT based on Racket. I guess that is the danger of Scheme, it's so easy to reimplement the base language that everyone is doomed to spending lifetimes reimplementing the standard libraries.


Perhaps the next "next Java" or "next C++" had better focus on also being a more or less universal platform, such that the reimplementation of standard libraries becomes a thing of the past? The CLR strove to be this, but this didn't take off because of its association with Microsoft.

The "designed to be hosted" structure of Clojure points the way to how this could be approached. Stallman's designs for Scheme and GUILE are along these lines as well.


Since UNCOL people keep on trying, but in the end it always ends up not quite there.


There are quite a few Scheme implementations, and Racket isn't necessarily the obvious choice. However, it does surprise me to see a reimplementation rather than using at least one of the existing implementations.


Well, I mention Racket because it has extensive tooling for new language creation (I've seen C-like, Java-like, and SQL-like languages implemented in it), and they've done so much work in creating a very extensive standard library that compiles and optimizes down to relatively simple Scheme base language. You basically get tools and libraries and optimizations and other languages "for free" if you use Racket, much like with the CLR, but in a completely open-source, could-be-statically-compiled-if-you-want way.


I can think of some reasons you might not want to build it on Racket. I think Racket is fantastic, but if you are developing some novel variety of Scheme or whatever then you might want to have control over "low level" (I'm sorry, I dislike that term) details like how closures get allocated or the evaluation order of things. It's perfectly cool to use Racket to write the implementation of such things though, but maybe as a more traditional language implementation. Of course you're right that it's much smarter to let other people solve the problems you don't care about, so most of the time Racket would be a sensible platform to build on top of.


Maybe you don't want to get all those features for free. Maybe you want the opposite: to not have those features at all.

If you are going to build a Lisp processor, then you probably don't want a Lisp compiler or interpreter in the traditional sense, which is what Racket gives you. Maybe what you want is an interpreter in hardware.


I'm not exactly sure Racket existed when this project was created. Furthermore, Racket is non-standard. Which is really the issue with Scheme. Prior to Racket there were SLIB and SRFIs. Which are still non-standard, but at least more universal.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: