Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #1234 > unrolled thread

Writing a forth kernel

Started byusao <rwatki@gmail.com>
First post2011-04-16 18:11 -0700
Last post2011-04-27 02:09 +0100
Articles 11 — 8 participants

Back to article view | Back to comp.lang.forth


Contents

  Writing a forth kernel usao <rwatki@gmail.com> - 2011-04-16 18:11 -0700
    Re: Writing a forth kernel BruceMcF <agila61@netscape.net> - 2011-04-16 19:18 -0700
    Re: Writing a forth kernel "P.M.Lawrence" <pml540114@gmail.com> - 2011-04-17 00:21 -0700
    Re: Writing a forth kernel Jan Coombs <jan_2011-02@murray-microft.co.uk> - 2011-04-17 10:40 +0100
      Re: Writing a forth kernel Chris Hinsley <chris.hinsley@gmail.com> - 2011-04-25 16:17 +0100
        Re: Writing a forth kernel Jan Coombs <jan_2011-02@murray-microft.co.uk> - 2011-04-29 00:51 +0100
      Re: Writing a forth kernel wzab <wzab01@gmail.com> - 2011-05-13 09:04 -0700
        Re: Writing a forth kernel Jan Coombs <jan_2011-02@murray-microft.co.uk> - 2011-05-13 23:49 +0100
    Re: Writing a forth kernel Albert van der Horst <albert@spenarnc.xs4all.nl> - 2011-04-17 22:38 +0000
    Re: Writing a forth kernel Tarkin <tarkin000@gmail.com> - 2011-04-26 08:14 -0700
      Re: Writing a forth kernel Chris Hinsley <chris.hinsley@gmail.com> - 2011-04-27 02:09 +0100

#1234 — Writing a forth kernel

Fromusao <rwatki@gmail.com>
Date2011-04-16 18:11 -0700
SubjectWriting a forth kernel
Message-ID<cea3f9ee-8e66-4a64-acda-53e46ace819c@34g2000pru.googlegroups.com>
Im working on a home-brew 12-bit CPU, and would like to impelement
FORTH on it. Where can I locate details on how to implement a kernel
using assembly?

[toc] | [next] | [standalone]


#1235

FromBruceMcF <agila61@netscape.net>
Date2011-04-16 19:18 -0700
Message-ID<0dd67de9-30ae-400f-aac1-473f82a2aaf0@e21g2000vbz.googlegroups.com>
In reply to#1234
On Apr 16, 9:11 pm, usao <rwa...@gmail.com> wrote:
> Im working on a home-brew 12-bit CPU, and would like to impelement
> FORTH on it. Where can I locate details on how to implement a kernel
> using assembly?

"Moving Forth" is one introduction that demonstrates implementing a
Forth on multiple microprocessors. It can be found in the
"Documentation" link in the sidebar of the main page at:

http://www.camelforth.com/news.php

[toc] | [prev] | [next] | [standalone]


#1240

From"P.M.Lawrence" <pml540114@gmail.com>
Date2011-04-17 00:21 -0700
Message-ID<8d643d28-3623-4609-b483-d983f35bb66f@b13g2000prf.googlegroups.com>
In reply to#1234
usao wrote:
> Im working on a home-brew 12-bit CPU, and would like to impelement
> FORTH on it. Where can I locate details on how to implement a kernel
> using assembly?

If your priority is getting one working, rather than working
efficiently, you should google for Eforth or Hforth to see how those
went for that priority. They start from having an assembler or even
just machine code rather than using another Forth. Of course, the idea
is to use any Forth set up that way to implement a more efficient one
later. P.M.Lawrence.

[toc] | [prev] | [next] | [standalone]


#1247

FromJan Coombs <jan_2011-02@murray-microft.co.uk>
Date2011-04-17 10:40 +0100
Message-ID<abWdnfSMsqLrKDfQnZ2dnUVZ8sudnZ2d@brightview.co.uk>
In reply to#1234
On 17/04/11 02:11, usao wrote:
> Im working on a home-brew 12-bit CPU, and would like to impelement
> FORTH on it. Where can I locate details on how to implement a kernel
> using assembly?

This recent Novix style CPU is about the same size as yours, and 
has documentation, code support and applications:

   "J1 is a small (200 lines of Verilog) stack-based CPU, intended
   for FPGAs. A complete J1 with 16Kbytes of RAM fits easily on a
   small Xilinx FPGA"

   http://www.excamera.com/sphinx/fpga-j1.html

I'm part way through translating the code into MyHDL, a sort of 
interactive hardware development environment. This is a learning 
exercise for me, so, if I haven't learned enough I'll have a go at 
Bernd Paysan's b16 processor next.

For machines this small the compiler is often PC hosted, but it 
might be interesting to include one on a very small target like one 
of these.

Jan Coombs

[toc] | [prev] | [next] | [standalone]


#1516

FromChris Hinsley <chris.hinsley@gmail.com>
Date2011-04-25 16:17 +0100
Message-ID<2011042516174712230-chrishinsley@gmailcom>
In reply to#1247
On 2011-04-17 10:40:06 +0100, Jan Coombs said:

> On 17/04/11 02:11, usao wrote:
>> Im working on a home-brew 12-bit CPU, and would like to impelement
>> FORTH on it. Where can I locate details on how to implement a kernel
>> using assembly?
> 
> This recent Novix style CPU is about the same size as yours, and has 
> documentation, code support and applications:
> 
>    "J1 is a small (200 lines of Verilog) stack-based CPU, intended
>    for FPGAs. A complete J1 with 16Kbytes of RAM fits easily on a
>    small Xilinx FPGA"
> 
>    http://www.excamera.com/sphinx/fpga-j1.html
> 
> I'm part way through translating the code into MyHDL, a sort of 
> interactive hardware development environment. This is a learning 
> exercise for me, so, if I haven't learned enough I'll have a go at 
> Bernd Paysan's b16 processor next.
> 
> For machines this small the compiler is often PC hosted, but it might 
> be interesting to include one on a very small target like one of these.
> 
> Jan Coombs

Jan, here's a version of the J1 I did, with a bit of code tidying and 
renameing to help me understand it better. Any errors are mine and not 
nesseserally the original authors.

I was going to paramaterise it so you can pick and choose the width of 
the registers and depth of the stacks etc. But in case this helps at 
all have a copy of this.

module j1(
	 input i_clk, input i_rst, input [15:0] io_din,
	 output io_rd, output io_wr, output [15:0] io_addr, output [15:0] io_dout);

	// pc register
	reg [12:0] pc;
	reg [12:0] _pc;

	// instruction word
	wire [15:0] insn;

	// data stack
	reg [4:0] dsp;		// data stack index
	reg [4:0] _dsp;		// next data stack index

	reg [15:0] ds0;	// current top of data stack
	reg [15:0] _ds0;	// next top of data stack

	// return stack
	reg [4:0] rsp;		// return stack index
	reg [4:0] _rsp;		// next return stack index
	reg [15:0] _rs0;	// next top of return stack

	wire _dsW;			// data stack write signal
	reg _rsW;			// return stack write signal

	wire _ramWE;		 // RAM write enable
	wire [15:0] ramrd;

	// next pc value if we need it
	wire [15:0] pc_plus_1;
	assign pc_plus_1 = pc + 1;

	// internal data and return stacks.
	// each clock we may write the top of data stack
	// or the next top of return stack
	// plus we read out the next on data stack and current top of return stack
	reg [15:0] dstack[0:31];
	reg [15:0] rstack[0:31];
	always @(posedge i_clk)
	begin
		if (_dsW) dstack[_dsp] = ds0;
		if (_rsW) rstack[_rsp] = _rs0;
	end
	wire [15:0] ds1 = dstack[dsp];
	wire [15:0] rs0 = rstack[rsp];

	// opcode for the ALU operation.
	// For jump and call the operation is T, for 0branch it is N.
	// For ALU ops it is loaded from the instruction field.
	reg [3:0] opcode;
	always @(*)
	begin
		case (insn[14:13])
			2'b00: opcode = 0;			// jump
			2'b10: opcode = 0;			// call
			2'b01: opcode = 1;			// 0branch
			2'b11: opcode = insn[11:8];	// ALU
		endcase
	end

	// this bit is specific to your FPGA !
	// it's a dual port ram with A and B channels
	// instructions are coming from A
	`define RAMS 3
	`define w (16 >> `RAMS)
	`define w1 (`w - 1)
	genvar i;
	generate
		for (i = 0; i < (1 << `RAMS); i=i+1)
		begin : ram
			// RAMB16_S18_S18
			RAMB16_S2_S2
			ram(
			.DIA(0),
			// .DIPA(0),
			.DOA(insn[`w*i+`w1:`w*i]),
			.WEA(0),
			.ENA(1),
			.CLKA(i_clk),
			.ADDRA({_pc}),

			.DIB(ds1[`w*i+`w1:`w*i]),
			// .DIPB(2'b0),
			.WEB(_ramWE & (_ds0[15:14] == 0)),
			.ENB(|_ds0[15:14] == 0),
			.CLKB(i_clk),
			.ADDRB(_ds0[15:1]),
			.DOB(ramrd[`w*i+`w1:`w*i]));
		end
	endgenerate

	// compute next top of data stack
	always @(*)
	begin
		if (insn[15])
		begin
			// immediate value from instruction word
			_ds0 = {1'b0, insn[14:0]};
		end
		else
		begin
			// do the alu opcode
			case (opcode)
				4'b0000: _ds0 = ds0;
				4'b0001: _ds0 = ds1;
				4'b0010: _ds0 = ds0 + ds1;
				4'b0011: _ds0 = ds0 & ds1;
				4'b0100: _ds0 = ds0 | ds1;
				4'b0101: _ds0 = ds0 ^ ds1;
				4'b0110: _ds0 = ~ds0;
				4'b0111: _ds0 = {16{(ds1 == ds0)}};
				4'b1000: _ds0 = {16{($signed(ds1) < $signed(ds0))}};
				4'b1001: _ds0 = ds1 >> ds0[3:0];
				4'b1010: _ds0 = ds0 - 1;
				4'b1011: _ds0 = rs0;
				4'b1100: _ds0 = |ds0[15:14] ? io_din : ramrd;
				4'b1101: _ds0 = ds1 << ds0[3:0];
				4'b1110: _ds0 = {rsp, 3'b000, dsp};
				4'b1111: _ds0 = {16{(ds1 < ds0)}};
			endcase
		end
	end

	wire is_alu = (insn[15:13] == 3'b011);
	wire is_lit = (insn[15]);

	assign io_rd = (is_alu & (insn[11:8] == 4'hc));
	assign io_wr = _ramWE;
	assign io_addr = ds0;
	assign io_dout = ds1;

	assign _ramWE = is_alu & insn[5];
	assign _dsW = is_lit | (is_alu & insn[7]);

	// data and return stack deltas if needed
	wire [1:0] dd = insn[1:0];
	wire [1:0] rd = insn[3:2];

	always @(*)
	begin
		if (is_lit)
		begin
			// literal
			_dsp = dsp + 1;
			_rsp = rsp;
			_rsW = 0;
			_rs0 = _pc;
		end
		else if (is_alu)
		begin
			// alu op
			_dsp = dsp + {{3{dd[1]}}, dd};
			_rsp = rsp + {{3{rd[1]}}, rd};
			_rsW = insn[6];
			_rs0 = ds0;
		end
		else
		begin
			// jump, call or 0branch
			// what happens to data stack
			if (insn[15:13] == 3'b001)
			begin
				// 0branch we drop the condition
				_dsp = dsp - 1;
			end
			else
			begin
				_dsp = dsp;
			end

			// what happens to return stack
			if (insn[15:13] == 3'b010)
			begin
				// call
				_rsp = rsp + 1;
				_rsW = 1;
				_rs0 = {pc_plus_1[14:0], 1'b0};
			end
			else
			begin
				// jump or 0branch
				_rsp = rsp;
				_rsW = 0;
				_rs0 = _pc;
			end
		end
	end

	// what the next pc is going to be
	always @(*)
	begin
		if (i_rst)
		begin
			// reset
			_pc = pc;
		end
		else
		begin
			if ((insn[15:13] == 3'b000)
				| ((insn[15:13] == 3'b001) & (|ds0 == 0))
				| (insn[15:13] == 3'b010))
			begin
				// going to be jump, 0branch or call
				_pc = insn[12:0];
			end
			else if (is_alu & insn[12])
			begin
				// alu op also includes a return
				_pc = rs0[15:1];
			end
			else
			begin
				// or just moving on to next instruction
				_pc = pc_plus_1;
			end
		end
	end

	// each clock update to the next state or reset
	always @(posedge i_clk)
	begin
		if (i_rst)
		begin
			// reset
			pc <= 0;
			dsp <= 0;
			rsp <= 0;
			ds0 <= 0;
		end
		else
		begin
			// next state
			pc <= _pc;
			dsp <= _dsp;
			rsp <= _rsp;
			ds0 <= _ds0;
		end
	end
endmodule

[toc] | [prev] | [next] | [standalone]


#1636

FromJan Coombs <jan_2011-02@murray-microft.co.uk>
Date2011-04-29 00:51 +0100
Message-ID<laqdnY7fgrznYCTQnZ2dnUVZ8mednZ2d@brightview.co.uk>
In reply to#1516
On 25/04/11 16:17, Chris Hinsley wrote:
> Jan, here's a version of the J1 I did, with a bit of code tidying
> and renameing to help me understand it better. Any errors are mine
> and not nesseserally the original authors.

Mine was done for similar reasons, and also to help me learn to 
read Verilog, and write MyHDL.  The curent version is a 
self-contained test which runs a few hand assembled instructions, 
and exports verilog and VHDL files for synthesis.  Please email me 
if you'd like to play with it. (anyone?)

> I was going to paramaterise it so you can pick and choose the width
> of the registers and depth of the stacks etc. But in case this
> helps at all have a copy of this.

Thanks, it helps to see the same ideas wrapped up in someone else's 
words.  My J1 might also stagnate now, since code conversion was my 
main goal.

Parameterisation sound good, but perhaps requires extra work to 
optimise the opcode sets.  I have a compact instruction sets for 
four and nine bit word sizes, and am wondering if there is any 
interest in including floating point support in a very small core.

Jan Coombs.

[toc] | [prev] | [next] | [standalone]


#2016

Fromwzab <wzab01@gmail.com>
Date2011-05-13 09:04 -0700
Message-ID<6c336ca4-5f35-44cb-9819-173e7effdd45@s11g2000yqj.googlegroups.com>
In reply to#1247
On Apr 17, 11:40 am, Jan Coombs <jan_2011...@murray-microft.co.uk>
wrote:
>
>    "J1 is a small (200 lines of Verilog) stack-based CPU, intended
>    for FPGAs. A complete J1 with 16Kbytes of RAM fits easily on a
>    small Xilinx FPGA"
>
>    http://www.excamera.com/sphinx/fpga-j1.html
>
> I'm part way through translating the code into MyHDL, a sort of
> interactive hardware development environment. This is a learning
> exercise for me, so, if I haven't learned enough I'll have a go at
> Bernd Paysan's b16 processor next.
>

Is the MyHDL version of J1 available? I'm interested in adding a
possibility
to work interactively (via UART or via JTAG-emulated serial console)
with J1,
defining new words and executing them.
I think that the MyHDL version could be easier to modify and to
debug...

TIA,
Wojtek Zabolotny

[toc] | [prev] | [next] | [standalone]


#2027

FromJan Coombs <jan_2011-02@murray-microft.co.uk>
Date2011-05-13 23:49 +0100
Message-ID<We6dnWhpf_ARKFDQnZ2dnUVZ7rKdnZ2d@brightview.co.uk>
In reply to#2016
On 13/05/11 17:04, wzab wrote:
> On Apr 17, 11:40 am, Jan Coombs<jan_2011...@murray-microft.co.uk>
> wrote:
>>
>>     "J1 is a small (200 lines of Verilog) stack-based CPU, intended
>>     for FPGAs. A complete J1 with 16Kbytes of RAM fits easily on a
>>     small Xilinx FPGA"
>>
>>     http://www.excamera.com/sphinx/fpga-j1.html
>>
> Is the MyHDL version of J1 available? I'm interested in adding a
> possibility
> to work interactively (via UART or via JTAG-emulated serial console)
> with J1,
> defining new words and executing them.
The j1 should be open to interactive software development, but I am 
not sure how. I will try to find out.

> I think that the MyHDL version could be easier to modify and to
> debug...
Yes, fast interactive hardware development appeals to me as well. 
What I have is capable of running any j1 code, but only currently 
tests a few hand assembled instructions.

I'd like to get the MyHDL version of the j1 up to distribution 
quality for free cores, as this would make a simple SOC with easy 
simulation of the core and hardware extensions.

Please email me for a copy of the code. Running the simulation will 
give you a taste of development with MyHDL.

Jan Coombs.

[toc] | [prev] | [next] | [standalone]


#1272

FromAlbert van der Horst <albert@spenarnc.xs4all.nl>
Date2011-04-17 22:38 +0000
Message-ID<ljtiwg.irp@spenarnc.xs4all.nl>
In reply to#1234
In article <cea3f9ee-8e66-4a64-acda-53e46ace819c@34g2000pru.googlegroups.com>,
usao  <rwatki@gmail.com> wrote:
>Im working on a home-brew 12-bit CPU, and would like to impelement
>FORTH on it. Where can I locate details on how to implement a kernel
>using assembly?

ciforth is based on assembly languages. Apart from the documentation of
individual Forths, there is documentation for the generic part.
You may want to steal parts of this, or you can use the macro processing
to get a frame for your Forth where the high level words are already present
and the code words can be filled in.
If you are handy with a macro processor, you can generate the headers
differently than they are in the ciforth model.

If you adopt the ciforth model, you can even go all the way, and have a
system with tests, and documentation in the usual formats.

More in the site below, or google for ciforth.

Groetjes Albert

--
-- 
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

[toc] | [prev] | [next] | [standalone]


#1551

FromTarkin <tarkin000@gmail.com>
Date2011-04-26 08:14 -0700
Message-ID<c7583a5b-5d94-43a7-aa09-8cab3cb0e228@h38g2000yqn.googlegroups.com>
In reply to#1234
On Apr 16, 9:11 pm, usao <rwa...@gmail.com> wrote:
> Im working on a home-brew 12-bit CPU, and would like to impelement
> FORTH on it. Where can I locate details on how to implement a kernel
> using assembly?

In addition to "Moving Forth", I have found these to be helpful:

Build Your Own Forth:
http://www.figuk.plus.com/byof.htm

A seminal document by Dr. Moore himself-
Forth - A Language for Interactive Computing:
http://www.ultratechnology.com/4th_1970.html

If you grok x86 assembly in the GNU/Linux environment,
jonesforth is a work-through tutorial on Forth:
http://rwmj.wordpress.com/2010/08/07/jonesforth-git-repository/

HTH,
  Tarkin

[toc] | [prev] | [next] | [standalone]


#1565

FromChris Hinsley <chris.hinsley@gmail.com>
Date2011-04-27 02:09 +0100
Message-ID<2011042702093197080-chrishinsley@gmailcom>
In reply to#1551
On 2011-04-26 16:14:43 +0100, Tarkin said:

> On Apr 16, 9:11 pm, usao <rwa...@gmail.com> wrote:
>> Im working on a home-brew 12-bit CPU, and would like to impelement
>> FORTH on it. Where can I locate details on how to implement a kernel
>> using assembly?
> 
> In addition to "Moving Forth", I have found these to be helpful:
> 
> Build Your Own Forth:
> http://www.figuk.plus.com/byof.htm
> 
> A seminal document by Dr. Moore himself-
> Forth - A Language for Interactive Computing:
> http://www.ultratechnology.com/4th_1970.html
> 
> If you grok x86 assembly in the GNU/Linux environment,
> jonesforth is a work-through tutorial on Forth:
> http://rwmj.wordpress.com/2010/08/07/jonesforth-git-repository/
> 
> HTH,
>   Tarkin

Have a look at what I've done extending Jones Forth.

https://sites.google.com/site/chrishinsley/Home

This was for iMac, but it would be easy to convert to another pltform.

Regards

Chris

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.forth


csiph-web