;-*- Mode:Text -*-

22 bit PC: 4MW, 32MB instructions
do 22 or 23 if going through map; else 21 is enough.

to-do:

1. static low memory, short calls, open-call, t-open-call

2. select old / new frame addresses for destinations

3. meaning of return-destination code vs. destination code

return PC saved in Hram:
	always PC+1 ?

call-0: in parallel with normal alu op.
	8-10 bit vector
	same hardware as traps?
	filled with normal cache "valid" bit status etc.?
	or single valid bit for whole area?

assuming ret-dest register?
	holds last ret-dest read/written from Hram?

add push / pop of return destination to all call / return stuff.

figure out when dest-addr reg is clocked.

check address setup time for Hram and freelist writes.

common stuff so far:
	H addressed by active for all second cycles?
	ret-dest clocked every cycle?

;;;;

call hardware operations start on the mid-instruction 35ns clock;
some complete in one half-cycle, others take both.
do any take more than two cycles?

all instructions get old frames as sources?
by "default", destinations get the new frames.
sometimes want old frames as destinations?
next instruction always gets new frames.
return-destination always gets restored state (state as of before the call).
return-then-open: what frames for destination? (between return and open vs. after open?)

try bidirectional / tri-state paths for Hram and frame passing

;;;;

ALU requires a DEST field:
	N-bits for frame-select (open, active, return, global ...)
	4 bits for offset within frame
CALL requires a return-destination:
	N-bit frame-select; 4-bit offset.
	RETURN uses return-destination frame and offset as destination
	instead of normal DEST.
CALL has two dest fields: dest and ret-dest
RETURN needs no dest field: dest is overridden by ret-dest; ret-dest is unused?

does RETURN use same frame-select-space for return-destination field
as an ALU op uses for DEST?

reg addr mux select input was using clock to select source / dest fields;
still select source addrs during read cycle,
now select dest or ret-dest during write.
normal dest is always from IR;
ret-dest is from ret-dest ram output, possibly through ret-dest reg.
use ret-dest reg for indirect dest?

brute-force:
reg addr mux was two-input, selected by clock.  source / dest reg addr.
now is four-input, selected by clock and ch-op.  source / source / dest / ret-dest ?

dest is already delayed two clocks from IR to write-cycle;
ret-dest is popped from Hret-dest by return instruction.
dest is from IR of return instruction; delay twice to get to write cycle.

that ret-dest will be selected is known at IR of return instruction,
but ret-dest value is not popped from Hret-dest until clock at end of IR cycle,
so it is really delayed only one clock.


return frame is only valid until next open (same frame is allocated again);
would a previous-active option for the active frame reg work OK?

;;;;;;;;;;;;;;;;

Frames available as source and destination bases:

Open:
	Frame to store arguments for function that is about to be called.

Active:
	Frame for current function local variables and the arguments
	the function was called with.

Return:
	Frame in which to store values to be returned by the active function.

Global:
	Frame number comes from instruction.

and possibly:

Return-destination:
	Frame and offset come from H(active)-return-dest.
	(no latch)

Indirect:
	Frame and offset is from previously computed value.

;;;;;;;;;;;;;;;;

Function-call operations:

Open:
	Create a new open frame in preparation for a function call.

	1. save open and active frames in H(free).
	2. allocate a new open frame.

	Source: before (open frame should not be sourced)
	Dest: after

	asserted during second cycle:
		H(free) <- active, open
	clocked at end of second cycle:
		open <- free
		increment free-pointer

Call:
	Call a function.  Make the current open frame become the active frame.

	IR bits for one source and for ALU operation are used for PC;
	ALU op or external path is wired to connect source and dest.
	(use one source and byte op; not ALU op)

	1. copy open frame pointer to active frame. (active was saved in OPEN)
	2. save the (return) PC and return-destination in the H(active). (new active)
	3. jump (set pc) to the code for the function to be called.

	Source: before (for new active, use open?)
	Dest: after.  (ever write into old active?)

	clocked at start of second cycle:
		active <- open
	asserted during second cycle:
		H(active) <- current PC, return-destination
	side effects:
		next PC selected is 24-bit addr from IR.
	use separate registers for active-to-ALU and active-to-HRAM.

Open-call:
	Create a new open frame, make it the active frame and call a function.
	Useful for calling single-argument functions: one instruction
	can compute an argument into the new open/active frame, store a
	return-destination, and call a function.
	Requires lots of IR bits ...

	1. save open, active, return PC and ret-dest in H(free).
	2. allocate a new open frame and also copy it to active.
	3. jump (set PC) to the function to be called.

	Source: 
	Dest:

	asserted during second cycle:
		H(free) <- active, open, ret-PC, ret-dest
	clocked at end of second cycle:
		open<- free
		increment free-pointer
	clocked at end of next first cycle: (if free can't go directly to open)
		active <- open

Return:
	Restore the frame environment to that prior to the preceding CALL.

	Force the return-destination to be used as the dest.

	1. copy active frame pointer to return frame.
	   (makes return values addressable through return frame)
	2. push active frame pointer onto frame freelist.
	3. pop open, active, PC and return-destination saved by preceding CALL.

	Source: before
	Dest: after; is forced to be the return-destination.

	clocked at start of second cycle:
		return <- active
		decrement free-pointer
	asserted during second cycle:
		free <- active  (check free-pointer setup before write)
		H addressed by active
	clocked at end of second cycle:
		retd, pc, active, open <- H(active)
		(retd is stored in dest-addr reg)

Tail-recursive-open:
	Copy the current open frame into a new frame, in preparation for
	a tail-recursive call, which will throw away the active frame as
	if returning and then start a new call by copying open to active.

	1. pop open and active frames and PC saved by preceding CALL;
	   save in temporary regs so as to not trash current open, active and PC.
	2. allocate a new open frame
	3. push temporary open, active and PC in location spec. by the new open frame.

	Source: before (open should not be sourced)
	Dest: after

	asserted during second cycle:
		H addressed by active
	clocked at end of second cycle:
		pctemp, activetemp, open <- H(active)
	asserted during next first cycle:
		H(free) <- pctemp, activetemp, open
	clocked at end of next first cycle: (start of next second cycle)
		open <- free
		increment free-pointer

Tail-recursive-call:
	Call a function.  Discard the active frame as if returning, and make the
	current open frame become the active frame.

	0. save ret-dest from H(active) in ret-dest-temp
		ret-dest-temp register, or what?
	1. push active frame pointer onto frame freelist
	2. copy the open frame pointer to the active frame.
	3. copy ret-dest-temp to new H(active)
	4. jump (set pc) to the code for the function to be called.

	Source: before (for new active, use open)
	Dest: after

	assumed asserted at during first cycle:
		H addressed by active
	clocked at start of second cycle:
		ret-dest <- H(active)
		decrement free-pointer
	asserted during second cycle:
		free <- active
	clocked at end of second cycle:
		active <- open
	asserted during next first cycle:
		H(active) <- ret-dest
	side effects:
		next PC selected is 24 bits from IR

return-then-open:
	Return as specified by the return PC and return-destination return code,
	but open a new frame "below" the current active frame.  The new
	frame becomes the open frame; the saved open and active frames
	from the frame above are saved in H(new-open-frame).  The saved active
	frame becomes the active frame.

	Do part of RETURN that restores PC and open frame.  Preserve active
	frame; copy return value for active frame directly into a new (free)
	frame.  Open a new frame and store this active and the open frames
	in the Hram indexed by it.  Copy the active frame to the return frame;
	push the active frame onto the freelist.  Copy the saved active
	frame to the active frame.

	1. Pop open and active frames and PC saved in H(active) by preceding
	   CALL, into open, activetemp and PC.
	2. allocate a new open frame.
	3. save the open and activetemp frames H(open).
	4. copy the active frame pointer to the return frame.
	5. push the active frame pointer onto the frame freelist.
	6. copy the activetemp frame to the active frame.

return-then-tail-recursive-open
	Do a return as specified by a return-destination return code,
	but t-open a new frame "below" the current active frame and make
	it be the active frame.
	Do part of RETURN that restores PC and open frame.  Preserve active
	frame; copy return value for active frame directly into a new (free)
	frame.  Open this new frame and store the return-active and open frames
	in the Hram indexed by it.  Copy the active frame to the return frame;
	Push the active frame onto the freelist.  Copy the return-active
	frame to the active frame.

	1. Pop open and active frames and PC saved by preceding CALL into
	   open, activetemp and PC.
	2. allocate a new open frame.
	3. copy the saved active, open and PC from H(activetemp) to H(free).
	4. copy the active frame pointer to the return frame.
	5. push the active frame pointer onto the frame freelist.
	6. copy the activetemp frame to the active frame.

cancel-open:
	Undo an open.

	1. push the open frame on the freelist.
	2. restore active and open from H(open).

;;;;;;;;;;;;;;;;


call-hardware operations directly executable from IR:
	open
	call
	open-call
	return
	t-open
	t-call
	t-open-call

call-hardware operations executable only as return-destinations:
	no-op (normal return)
	return-then-open
	return-then-t-open

call-hardware operations that specify a return-destination:
	call
	open-call

call-hardware frame-select inputs:
	open
	active
	return
	global
old-frame-state select inputs:
	previous open-frame before this instruction
	open frame in between return-then-open
	open frame after return-then-open
	active ...?