Re: [stack] Concatenative Hardware

"Christopher Diggins" <[email protected]>
Newsgroups gmane.comp.lang.concatenative
Message-ID <[email protected]>
On 11/2/07, William Tanksley, Jr <[email protected]> wrote:
> Christopher Diggins <[email protected]> wrote:
>  > So I've been thinking about concatenative hardware lately. Here is a
>  > single-stack machine instruction set:
>
>  Interesting. I've played a lot with stack hardware (designed a
>  complete processor for a HW class), so your twist on the subject is
>  very thought-provoking.
>
>  > 0: JZ (val fxn -> ) // jump to fxn if value is below zero
>  > 1: CALL (fxn) // push return address and jump to fxn
>  > 2: LTEQ (val val -> bool) // compare values
>  > 3: AND (val val -> val) // perform bitwise and
>  > 4: XOR (val val -> val) // perform XOR operation
>  > 5: SHL (val val -> val) // shift-left
>  > 6: DUP (a -> a a)  // duplicate top-value
>  > 7: QTE (val -> fxn) // create a thunk
>  > 8: COMP (fxn fxn -> fxn) // compose two functions (append their contents)
>  > 9: POP (a -> ) // pop value from stack
>  > 10: DIP (a fxn -> a) // applies function to below top of stack
>  > 11: SWP (a b -> b a) // swap top two items
>
>  Very high-level... You'll need more detailed semantics for that to
>  work at all (memory management will be a BEAR for you).

Yes, this is where I am stuck.

> Of course,
>  you're entirely missing ADD and such. Oh, and I see you've got a
>  comparison instruction, but no conditional call or branch. I assume
>  you intended to imply those, of course.

Whoops some mistakes. Especially the missing ADD.

>  You might want to look at Henry Baker's papers on a similar topic.
>  Check out his paper on O(1) instructions which could implement a VERY
>  flexible VM that doesn't require GC;
>  http://home.pipeline.com/~hbaker1/LinearLisp.html. "Hash cons"ing is
>  very important, and might even fit into hardware.

Great, I'll look into it.

>  Once you get memory management a bit more simple, you need to
>  determine the implications of your instruction encoding. You don't
>  explain your encoding, which leads me to suspect that each instruction
>  is encoded as a byte.

4 bits is my goal.

> Needless to say, bit packing is a LOT nicer,
>  even when you're doing a VM.
>
>  The worst implication of your instruction encoding -- and this isn't
>  something you've made explicit -- is that your instructions _appear_
>  to be stored in CONS cells.

I'm looking for alternatives, I don't like the idea of CONS cells. I'm
thinking of a linked list of mini-stacks, but this is just a vague
notion at this point.

> This implies that there's one per cell.
>  That's MAJORLY inefficient in every way, needless to say.

Yep.

> It's obvious
>  that one optimization would be to pack multiple instructions into a
>  single CONS cell,

I'm thinking of 32 bit stack, which can contain 8 4 bit instructions.

> but that could well give you worse problems, as then
>  you have to decide how to handle CALLs. Perhaps the answer should be
>  that a CALL is always the CDR of a CONS pair...

Interesting idea.

>  > So essentially we can use the data stack also as a return address
>  > stack. This is a zero operand instruction set, so it is very compact
>  > and can be implemented efficiently, but it takes a lot of instructions
>  > to do simple things (e.g. accessing items deep in the stack).
>
>  "Doctor, it hurts when I do this." ;-)
>
>  It's possible that you shouldn't consider "accessing items deep in the
>  stack" to be a "simple thing".
>
>  > The "dip" instruction is so important I'm tempted to include variants:
>  > 12: DIP2 : (a b fxn -> a b)
>  > 13: DIP3 : (a b c fxn -> a b c)
>  > 14: DIP4 : (a b c d fxn -> a b c d)
>
>  The DIP instruction is so complex, high-overhead, and dependent on
>  precise details of user needs that I'm tempted to not include it.

Good point. Besides I need those slots for ADD, a PUSH, and possibly a NOOP.

>  > 15: open for suggestions
>
>  YES! 4 bits! (Assuming you don't want math or conditionals...)

JZ was the conditional (which I am thinking of combining with LTEQ, to
make JLE (Jump if less than or equal)  when do we use LTEQ outside of
a branch anyway, if we need a true LTEQ we can say: JLE

>  > Of course "DIP" can be implemented as "SWP QTE COMP CALL", but I'm
>  > concerned about performance. The "DIP" is one of the most frequent
>  > instructions in my code.
>
>  It seems to me that DIP is inherently complex -- you don't want to
>  stretch your clock cycle to accommodate a single instruction.

That is a good point.

> Much
>  better to let users implement DIP the way they need it.

Its just that when I generate Cat from C code algorithmically it
generates a ton of DIPs.

>  Although I just noticed you use CONCAT instead of CONS. Hmm. That's
>  another inherently complex instruction (it takes linear time).

Not neccessarily, if we use lists with tail pointers. However, that is ugly.

>  > Anyway, hopefully this makes sense to my fellow concatenators. I'd
>  > love to hear thoughts and suggestions. I'm pretty naive when it comes
>  > to hardware.
>
>  Think about this carefully... Generally speaking, the minimal
>  requirement for hardware is that all instructions should be O(1).

Good idea.

> I've
>  seen that requirement skipped... Chuck Moore's processors use cycle
>  times so fast that there's isn't time for the carry flag to propagate
>  on addition, so when you do addition you have to allow the stack to
>  settle in the ALU before you read the result of the addition (it's
>  simpler in practice than it sounds). Most CISCs have varying
>  instruction times. But in general it makes things messy.
>
>  Whatever you do, you do NOT want any single instruction to NOT take
>  constant time.

Great point. Thank you for mentioning it.

Thanks a lot for sharing your ideas!

- Christopher
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.