Commit c662be05 authored by bp's avatar bp

initial checkin

git-svn-id: https://www.forth-ev.de/repos/b16@2 3b8d8251-53f3-0310-8f3b-fd1cb8370982
parent 3abf29c5
This diff is collapsed.
#
SOURCES = b16.lyx b16-eng.lyx Makefile \
b16.nw b16-eng.nw b16.v b16-eval.v b16-eval-test.v \
boot.asm b16.asm usb.asm b16_eval.rbf la.c b16.fs \
COPYING b16.pdf b16-eng.pdf hex2boot \
add-mem b16-usb-test.v usb-test.v usb.v \
b16-eval-usb.v b16-eval-usb-test.v usbphys.v ram1024.v stackram.v \
sieve.asm b16-gcc-slides.lyx gcc/b16.h gcc/b16.md.in
all: b16.v b16.pdf b16-eng.pdf la
gcc/b16.md: gcc/b16.md.in
m4 <$< >$@
%.nw: %.lyx
lyx --execute "buffer-export literate" $<
%.tex: %.nw
noweave -delay -latex $< | sed -e 's/1<<dep/1<{}<dep/g' >$@
latex $@
%.v: %.nw
notangle -Rb16.v $< >$@
%.dvi: %.tex
latex $<
%.ps: %.dvi
dvips -Pams -Pcmz -Ppdf $< -o $@
%.ps.gz: %.ps
gzip <$< >$@
%.pdf: %.ps
ps2pdf $< $@
la: la.c
gcc -O2 la.c -o la
dist: $(SOURCES)
mkdir b16
tar cf - $(SOURCES) | (cd b16; tar xf -)
tar jcf b16.tar.bz2 b16
rm -rf b16
#!/bin/bash
raml="$(grep 'RAM instance.*bootraml' exemplar.log | tail -1 | cut -f2 -d "'")_ix38"
ramh="$(grep 'RAM instance.*bootramh' exemplar.log | tail -1 | cut -f2 -d "'")_ix38"
awk "/\(instance $ramh/"' { print; print " (property LPM_FILE (string \"bootramh.mif\"))" }
'"/\(instance $raml/"' { print; print " (property LPM_FILE (string \"bootraml.mif\"))" }
!/\(instance ('"$ramh|$raml"')/ { print }' <b16_eval.edf >b16.edf
This diff is collapsed.
This diff is collapsed.
// b16 evalboard test environment
/*
* $Log: b16-eval-test.v,v $
* Revision 1.5 2003/01/06 20:35:21 bernd
* Changes to run with Icarus Verilog
* USB interrupts
* Added interrupts to the b16 core
*
* Revision 1.4 2002/03/31 23:08:39 bernd
* Made downloader work. Improved testbench to allow serial communication
*
* Revision 1.3 2002/03/24 17:46:15 bernd
* Added bit-bang input
*
* Revision 1.2 2002/03/23 21:35:57 bernd
* Made b16 faster
*
* Revision 1.1 2002/02/17 23:18:58 bernd
* Initial version of test environment
*
*/
`include "b16-eval.v"
`include "b16.v"
module eval_test;
parameter l=16;
reg clk, reset;
reg `L din;
wire `L dout, a;
wire `L d;
wire wr_b, rd_b, ble_b, bhe_b;
b16_eval flk10k30e(clk, reset, din, dout, a, d, wr_b, rd_b, ble_b, bhe_b);
integer oldtime;
always @(dout)
begin
$display("%d: dout <= %b", $time-oldtime, dout);
oldtime <= $time;
end
initial
begin
reset <= 1;
clk <= 0;
#1000 reset <= 0;
forever #50 clk <= ~clk;
end
task send_byte;
input [7:0] byte;
begin
#8700 din[0] <= 0;
#8700 din[0] <= byte[0];
#8700 din[0] <= byte[1];
#8700 din[0] <= byte[2];
#8700 din[0] <= byte[3];
#8700 din[0] <= byte[4];
#8700 din[0] <= byte[5];
#8700 din[0] <= byte[6];
#8700 din[0] <= byte[7];
#8700 din[0] <= 1;
#8700 din[0] <= 1;
end
endtask
initial
begin
din <= 16'h0001;
#100000 send_byte(8'h30); // start bit
send_byte(8'h03);
send_byte(8'h02);
send_byte(8'h04);
send_byte(8'h12);
send_byte(8'h34);
send_byte(8'h56);
send_byte(8'h78);
#100000 send_byte(8'h31);
send_byte(8'h03);
send_byte(8'h02);
send_byte(8'h04);
end
endmodule // eval_test
// test b16+usb eval code
/*
* $Log$
*/
module test;
wire [15:0] a0, a1, d0, d1;
wire DP, DN, send0, send1;
reg clk, nreset;
assign { DP, DN } = (send0 | send1) ? 2'bzz : 2'b10;
b16_eval_usb #(16, "master.hex")
core0(clk, nreset, a0, d0, wr_b0, rd_b0, ble_b0, bhe_b0,
DP, DN, dif0, send0, dp0, dn0);
b16_eval_usb #(16, "slave.hex")
core1(clk, nreset, a1, d1, wr_b1, rd_b1, ble_b1, bhe_b1,
DP, DN, dif1, send1, dp1, dn1);
usbphys usbp0(DP, DN, dif0, send0, dp0, dn0);
usbphys usbp1(DP, DN, dif1, send1, dp1, dn1);
initial
begin
$dumpfile("b16-eval-usb.vcd");
$dumpvars();
nreset <= 0;
clk <= 0;
#10000 nreset <= 1;
repeat(10000)
#10 clk <= ~clk;
$finish;
end
endmodule // test
// Interface to elements on the evaluation board
/*
* $Log: b16-eval-usb.v,v $
* Revision 1.2 2004/05/02 21:40:21 bernd
* Changes for USB and Cyclone
*
* Revision 1.1 2004/05/02 19:22:22 bernd
* Initial checkin
*
*/
`define L [l-1:0]
module b16_eval_usb(clk, nreset, a, d, wr_b, rd_b, ble_b, bhe_b,
DP, DN, dif, send, dp, dn);
parameter l=16, bootram="b16.hex";
input clk, nreset;
output `L a;
inout `L d;
output wr_b, rd_b, ble_b, bhe_b;
input DP, DN, dif;
output send, dp, dn;
wire `L mem_addr, addr, dout, dout_boot, dma, data;
wire r, mem_r, intreq, intack, reqr, reqw;
wire [3:0] pid;
wire [7:0] intvec = { 1'b0, pid, 3'b000 };
wire [1:0] w, mem_w;
reg [2:0] sel;
reg [1:0] dout24;
reg ack;
wire nrst = nreset;
wire reset = nreset;
wire cpu_rw = |w | r;
always @(negedge cpu_rw or negedge reqr or negedge reqw)
ack <= reqr | reqw;
assign mem_r = ack ? reqr : r;
assign mem_w = ack ? {(2){reqw}} : w;
assign mem_addr = ack ? dma : addr;
wire usb_sel = sel[2];
wire mem_sel = ~usb_sel;
cpu #(1) b16(clk, nrst, addr, r, w, data, dout, intreq, intack, intvec);
usb #(1) usb1(clk, reset, DP, DN, dif, send, dp, dn,
usb_sel, addr[2:1], r, w, dma, reqr, reqw, ack, data, data,
pid, intreq, intack);
ram1024 #(bootram) ram(mem_addr[10:1], w, ~clk, data, sel[1] & |w, dout_boot);
assign a = { 1'b0, mem_addr[l-1:1] };
assign d = mem_r ? 16'hzzzz : data;
always @(addr)
if(&addr[15:3]) sel <= 3'b100;
else if(addr[15:11] == 5'h00) sel <= 3'b010;
else sel <= 3'b001;
reg wr_b, rd_b, ble_b, bhe_b;
always @(clk or nrst or r or w or sel)
if(sel[0] & nrst) begin
rd_b <= ~r;
{ wr_b, ble_b, bhe_b } <= 3'b111;
if(!clk) begin
wr_b <= ~|w;
{ bhe_b, ble_b } <= ~w & { ~r, ~r };
end
end
else { wr_b, rd_b, ble_b, bhe_b } <= 4'b1111;
assign data = mem_w ? dout :
{ r, sel } == 4'b1010 ? dout_boot :
{ r, sel } == 4'b1010 ? d : 16'hzzzz;
endmodule
// Interface to elements on the evaluation board
`define L [l-1:0]
module b16_eval(clk, reset, din, dout, a, d, wr_b, rd_b, ble_b, bhe_b);
parameter l=16;
input clk, reset;
input `L din;
output `L dout, a;
inout `L d;
output wr_b, rd_b, ble_b, bhe_b;
wire `L addr, dwrite, a_out;
wire r, waits;
wire [1:0] w;
reg `L dout_out, data, a_old;
reg [2:0] sel;
reg [1:0] dout24;
wire [7:0] intvec = 0;
wire intreq = 0;
wire nrst = ~reset;
cpu b16(clk, nrst, addr, r, w, data, dwrite, intreq, intack, intvec);
assign d = r ? {(l){ 1'bz }} : dwrite;
assign a_out = { 1'b0, addr[l-1:1] };
always @(posedge clk)
a_old <= a_out;
assign a[0] = (a_out[0] & a_old[0]) ? 1'bz : a_out[0];
assign a[1] = (a_out[1] & a_old[1]) ? 1'bz : a_out[1];
assign a[2] = (a_out[2] & a_old[2]) ? 1'bz : a_out[2];
assign a[3] = (a_out[3] & a_old[3]) ? 1'bz : a_out[3];
assign a[4] = (a_out[4] & a_old[4]) ? 1'bz : a_out[4];
assign a[5] = (a_out[5] & a_old[5]) ? 1'bz : a_out[5];
assign a[6] = (a_out[6] & a_old[6]) ? 1'bz : a_out[6];
assign a[7] = (a_out[7] & a_old[7]) ? 1'bz : a_out[7];
assign a[8] = (a_out[8] & a_old[8]) ? 1'bz : a_out[8];
assign a[9] = (a_out[9] & a_old[9]) ? 1'bz : a_out[9];
assign a[10] = (a_out[10] & a_old[10]) ? 1'bz : a_out[10];
assign a[11] = (a_out[11] & a_old[11]) ? 1'bz : a_out[11];
assign a[12] = (a_out[12] & a_old[12]) ? 1'bz : a_out[12];
assign a[13] = (a_out[13] & a_old[13]) ? 1'bz : a_out[13];
assign a[14] = (a_out[14] & a_old[14]) ? 1'bz : a_out[14];
assign a[15] = (a_out[15] & a_old[15]) ? 1'bz : a_out[15];
assign dout[2] = (dout_out[2] & dout24[0]) ? 1'bz : dout_out[2];
assign dout[4] = (dout_out[4] & dout24[1]) ? 1'bz : dout_out[4];
assign { dout[15:5], dout[3], dout[1:0] } = { dout_out[15:5], dout_out[3], dout_out[1:0] };
always @(addr)
if(addr[15:2] == 14'h3fff) sel <= 3'b100;
else if(addr[15:11] == 5'h00) sel <= 3'b010;
else sel <= 3'b001;
always @(negedge clk or negedge nrst)
if(!nrst)
begin
dout_out <= 16'b1010_0101_0001_0101;
dout24 <= 2'b11;
end
else
begin
if(sel[2] & addr[1]) begin
if(w[1]) dout_out[15:8] <= dwrite[15:8];
if(w[0]) dout_out[07:0] <= dwrite[07:0];
end // if (sel[2] & addr[0])
dout24 <= { dout_out[2], dout_out[4] };
end
reg wr_b, rd_b, ble_b, bhe_b;
always @(clk or nrst or r or w or sel)
if(sel[0] & nrst) begin
rd_b <= ~r;
{ wr_b, ble_b, bhe_b } <= 3'b111;
if(!clk) begin
wr_b <= ~|w;
{ bhe_b, ble_b } <= ~w & { ~r, ~r };
end
end
else { wr_b, rd_b, ble_b, bhe_b } <= 4'b1111;
reg [7:0] bootraml[0:1023], bootramh[0:1023];
always @(negedge clk)
if(sel[1]) begin
if(w[1]) bootramh[addr[11:1]] <= d[15:8];
if(w[0]) bootraml[addr[11:1]] <= d[ 7:0];
if(&w) $display("bootram[%x] <= %x", { addr[11:1], 1'b0 }, d);
else begin
if(w[0]) $display("bootram[%x] <= %x", { addr[11:1], 1'b1 }, d[15:8]);
if(w[1]) $display("bootram[%x] <= %x", { addr[11:1], 1'b0 }, d[ 7:0]);
end
end
initial
begin
$readmemh("bootl.hex", bootraml);
$readmemh("booth.hex", bootramh);
end
integer oldtime;
initial oldtime = 0;
always @(sel or r or d or din or dout_out or addr)
begin
casez({ r, sel })
4'b1100: begin
data <= addr[1] ? dout_out : din;
if(!addr[1] && (($time-oldtime) != 0)) begin
$display("%d: Read din %x", $time-oldtime, din);
oldtime = $time;
end
end
4'b1010: data <= { bootramh[addr[11:1]], bootraml[addr[11:1]] };
4'b1001: data <= d;
4'b????: data <= 16'h0000;
endcase // case(sel)
end
endmodule
#LyX 1.3 created this file. For more info see http://www.lyx.org/
\lyxformat 221
\textclass slides
\begin_preamble
% Uncomment to print out only slides and overlays
%
%\onlyslides{\slides}
% Uncomment to print out only notes
%
%\onlynotes{\notes}
\end_preamble
\language german
\inputencoding latin1
\fontscheme ae
\graphics dvips
\paperfontsize default
\spacing single
\papersize a4paper
\paperpackage a4
\use_geometry 0
\use_amsmath 0
\use_natbib 0
\use_numerical_citations 0
\paperorientation landscape
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\defskip medskip
\quotes_language german
\quotes_times 2
\papercolumns 1
\papersides 1
\paperpagestyle default
\layout Slide
\lang english
Title
\layout Standard
\align center
\series bold
\size giant
Ein GCC fr den b16
\layout Standard
\align center
\series bold
\size giant
\noun on
Bernd Paysan
\layout Slide
Motivation
\layout Standard
\series bold
Motivation
\layout Itemize
Kunden wollen C
\layout Itemize
Sieht professionell aus
\layout Itemize
Weil's geht
\layout Itemize
Vorbild: GCC fr PicoJava
\layout Itemize
Codegre und Geschwindigkeit von C fr den Kunden weitgehend egal (8051
ist schlimmer)
\layout Slide
Machines
\layout Standard
\series bold
Unterschiedliche Machinen-Modelle
\layout Description
GCC: Register-Maschine mit komplexen Adressierungsarten (VAX, 68k)
\layout Description
b16: Stackmaschine mit explizitem Load/Store ber's A-Register
\layout Description
Unterschied: Unterschiedlicher geht's nicht
\layout Description
Lsung: Emulation der Register-Maschine,
\begin_inset Quotes pld
\end_inset
Register
\begin_inset Quotes grd
\end_inset
im RAM.
Bringt man den
\begin_inset Quotes gld
\end_inset
Register
\begin_inset Quotes grd
\end_inset
-Identifier in einem Byte unter, kriegt man so 128 16-Bit-Register.
\layout Slide
Befehlsformat
\layout Description
Register\SpecialChar ~
Quelle:
\family typewriter
%Rx
\begin_inset Formula $\Rightarrow$
\end_inset
x # >A A@
\begin_inset Formula $=$
\end_inset
x # @
\layout Description
Register\SpecialChar ~
Ziel:
\family typewriter
%Qx
\begin_inset Formula $\Rightarrow$
\end_inset
x # >A A!
\begin_inset Formula $=$
\end_inset
x # !
\layout Description
Addressierung:
\family typewriter
n[%Rx]
\begin_inset Formula $\Rightarrow$
\end_inset
x # @ n # + @/!
\layout Description
Literals:
\family typewriter
#n
\begin_inset Formula $\Rightarrow$
\end_inset
n #
\layout Description
Befehl:
\family typewriter
add %R1, %R2, %Q3
\begin_inset Formula $\Rightarrow$
\end_inset
1 # @ 2 # @ + 3 # !
\layout Description
Control\SpecialChar ~
Flow:
\family typewriter
bcpugt %R1, %R2, dest
\begin_inset Formula $\Rightarrow$
\end_inset
1 # @ 2 # @ com + dest jnc
\layout Slide
Verbesserung
\layout Standard
\series bold
Architektur-Anpassungen an C
\layout Standard
Eine Mglichkeit, den b16 fr den GCC kompakter zu machen, wre es, zwei
Befehle zu bauen, die die Schritte
\family typewriter
# >A A@/!
\family default
in einem Befehl codiert.
Dann mte man aber auf zwei andere Befehle verzichten.
Kompromiss:
\family typewriter
# >A
\family default
an Stelle von
\family typewriter
c#
\layout Standard
Destruktive Conditionals: Da diese Emulation nichts mit auf dem Stack herumliege
nde Reste von Vergleichen anfangen kann, sollte mal alle Conditionals (wie
in normalem Forth) das Argument konsumieren lassen.
\layout Slide
Machine Description File
\layout Standard
GCC sucht sich Befehle aus einer Machine-Description-File.
\layout Standard
Beispiel: Addition
\layout LyX-Code
\size small
(define_insn "addsi3"
\layout LyX-Code
\size small
[(set (match_operand:SI 0 "nonimmediate_operand" "=gD")
\layout LyX-Code
\size small
(plus:SI (match_operand:SI 1 "general_operand" "%gS")
\layout LyX-Code
\size small
(match_operand:SI 2 "general_operand" "gS")))]
\layout LyX-Code
\size small
""
\layout LyX-Code
\size small
"%S1 %S2 + %R0")
\layout Slide
Zu untersttzenden Befehle
\layout Standard
GCC erwartet eine Reihe Befehle: Moves, Arithmetik, Shift, Mul/Div, Compare,
bedingte Sprnge, Calls, Jumps (direkt und indirekt).
Auch block moves und Funktionen wie strlen() knnen direkt in Befehle umgesetzt
werden.
\layout Standard
Da viele Befehle hnlich aufgebaut sind, verwende ich den m4-Makroprozessor,
um weniger tippen zu mssen.
\layout Standard
Leider gibt's kein minimales Beispiel, von dem man ausgehen knnte, und
spter Erweiterungen hinzufgen knnte.
\layout Slide
.h-File
\layout Standard
Register und Fhigkeiten werden ber eine lngliche .h-Datei beschrieben.
Auch hier gibt's keine Minimal-Datei, von der man ausgehen knnte.
Einige der wichtigsten Makros sind:
\layout LyX-Code
#define TARGET_VERSION fputs ("(b16)", stderr);
\layout LyX-Code
#define BYTES_BIG_ENDIAN 1
\layout LyX-Code
#define BITS_PER_UNIT 8
\layout LyX-Code
#define UNITS_PER_WORD 2
\layout LyX-Code
#define POINTER_SIZE 16
\layout LyX-Code
#define FIRST_PSEUDO_REGISTER 128
\layout Slide
.c-File
\layout Standard
Fr die Code-Generierungs-Templates in der Machine-Description mu man C-Funktio
nen schreiben.
Diese Funktionen spucken die entsprechende Befehls-Sequenz aus.
Die wichtigste Funktion ist dabei
\family typewriter
print_operand
\family default
.
Diese Funktion wird fr jedes %-Argument im Assembler-String aufgerufen,
und bekommt den Buchstaben und das als Parameter.
\layout Slide
Optimierungen
\layout Standard
\series bold
Optimierungen
\layout Itemize
Unntige Zwischenergebnisse wegwerfen:
\begin_deeper
\layout Standard
\family typewriter
a # @ b # @ + z # ! z # @ c # @ + z # !
\layout Standard
wird zu
\family typewriter
a # @ b # @ + c # @ + z # !
\end_deeper
\layout Itemize
Vereinfachungen:
\begin_deeper
\layout Standard
\family typewriter
a # @ a # @ + z # !
\layout Standard
wird zu
\family typewriter
a # @ dup + z # !
\end_deeper
\layout Slide
Status
\layout Standard
\series bold
Status
\layout Standard
Was hier eingentlich stehen sollte, sind ein paar Ergebnisse (Benchmarks