URL
https://opencores.org/ocsvn/ssbcc/ssbcc/trunk
Subversion Repositories ssbcc
Compare Revisions
- This comparison shows the changes necessary to convert path
/ssbcc/trunk
- from Rev 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/macros/9x8/pushByte.py
29,4 → 29,5
printValue = argument[0]['value'] if type(argument[0]['value']) == str else '0x%X' % argument[0]['value']; |
printIx = argument[1]['value'] if type(argument[1]['value']) == str else '0x%X' % argument[1]['value']; |
ad.EmitPush(fp,v,'.pushByte(%s,%s)' % (printValue,printIx,)); |
|
ad.EmitFunction['.pushByte'] = emitFunction; |
/macros/9x8/push32.py
19,24 → 19,13
# Define the macro functionality. |
def emitFunction(ad,fp,argument): |
argument = argument[0]; |
if argument['type'] == 'value': |
v = argument['value']; |
elif argument['type'] == 'symbol': |
name = argument['value']; |
if not ad.IsSymbol(name): |
raise asmDef.AsmException('Symbol "%s" not recognized at %s' % (argument['value'],argument['loc'],)); |
ix = ad.symbols['list'].index(name); |
v = ad.symbols['body'][ix]; |
if len(v) != 1: |
raise asmDef.AsmException('Argument can only be one value at %s' % argument['loc']); |
v = v[0]; |
else: |
raise asmDef.AsmException('Argument "%s" of type "%s" not recognized at %s' % (argument['value'],argument['type'],argument['loc'],)); |
if type(v) != int: |
raise Exception('Program Bug -- value should be an "int"'); |
ad.EmitPush(fp,v%0x100,''); v >>= 8; |
ad.EmitPush(fp,v%0x100,''); v >>= 8; |
ad.EmitPush(fp,v%0x100,''); v >>= 8; |
printValue = argument['value'] if type(argument['value']) == str else '0x%08X' % argument['value']; |
ad.EmitPush(fp,v%0x100,'.push32(%s)' % printValue); |
v = ad.Emit_IntegerValue(argument); |
if not (-2**31 <= v < 2**32): |
raise asmDef.AsmException('Argument "%s" should be a 32-bit integer at %s' % (argument['value'],argument['loc'],)); |
printString = argument['value'] if type(argument['value']) == str else '0x%04X' % (v % 2**32); |
for ix in range(4-1): |
ad.EmitPush(fp,v%0x100,''); |
v >>= 8; |
ad.EmitPush(fp,v%0x100,'.push32(%s)' % printString); |
|
ad.EmitFunction['.push32'] = emitFunction; |
/macros/9x8/push24.py
0,0 → 1,31
# Copyright 2014, Sinclair R.F., Inc. |
|
def push24(ad): |
""" |
User-defined macro to push a 24 bit value onto the data stack so that the LSB |
is deepest in the data stack and the MSB is at the top of the data stack. |
Usage: |
.push24(v) |
where |
v is a 24-bit value, a constant, or an evaluated expression\n |
The effect is to push v%0x100, int(v/2**8)%0x100, and int(v/2**16)%0x100 onto |
the data stack.\n |
( - u_LSB u u_MSB ) |
""" |
|
# Add the macro to the list of recognized macros. |
ad.AddMacro('.push24', 3, [ ['','singlevalue','symbol'] ]); |
|
# Define the macro functionality. |
def emitFunction(ad,fp,argument): |
argument = argument[0]; |
v = ad.Emit_IntegerValue(argument); |
if not (-2**23 <= v < 2**24): |
raise asmDef.AsmException('Argument "%s" should be a 24-bit integer at %s' % (argument['value'],argument['loc'],)); |
printString = argument['value'] if type(argument['value']) == str else '0x%04X' % (v % 2**24); |
for ix in range(3-1): |
ad.EmitPush(fp,v%0x100,''); |
v >>= 8; |
ad.EmitPush(fp,v%0x100,'.push24(%s)' % printString); |
|
ad.EmitFunction['.push24'] = emitFunction; |
/macros/9x8/push16.py
9,7 → 9,7
where |
v is a 16-bit value, a constant, or an evaluated expression\n |
The effect is to push v%0x100 and int(v/2**8)%0x100 onto the data stack.\n |
( - u_LSB u u u_MSB ) |
( - u_LSB u_MSB ) |
""" |
|
# Add the macro to the list of recognized macros. |
18,22 → 18,12
# Define the macro functionality. |
def emitFunction(ad,fp,argument): |
argument = argument[0]; |
if argument['type'] == 'value': |
v = argument['value']; |
elif argument['type'] == 'symbol': |
name = argument['value']; |
if not ad.IsSymbol(name): |
raise asmDef.AsmException('Symbol "%s" not recognized at %s' % (argument['value'],argument['loc'],)); |
ix = ad.symbols['list'].index(name); |
v = ad.symbols['body'][ix]; |
if len(v) != 1: |
raise asmDef.AsmException('Argument can only be one value at %s' % argument['loc']); |
v = v[0]; |
else: |
raise asmDef.AsmException('Argument "%s" of type "%s" not recognized at %s' % (argument['value'],argument['type'],argument['loc'],)); |
if type(v) != int: |
raise Exception('Program Bug -- value should be an "int"'); |
ad.EmitPush(fp,v%0x100,''); v >>= 8; |
printValue = argument['value'] if type(argument['value']) == str else '0x%08X' % argument['value']; |
ad.EmitPush(fp,v%0x100,'.push16(%s)' % printValue); |
v = ad.Emit_IntegerValue(argument); |
if not (-2**15 <= v < 2**16): |
raise asmDef.AsmException('Argument "%s" should be a 16-bit integer at %s' % (argument['value'],argument['loc'],)); |
printString = argument['value'] if type(argument['value']) == str else '0x%04X' % (v % 2**16); |
ad.EmitPush(fp,v%0x100,''); |
v >>= 8; |
ad.EmitPush(fp,v%0x100,'.push16(%s)' % printString); |
|
ad.EmitFunction['.push16'] = emitFunction; |
/lib/9x8/deprecated/math.s
0,0 → 1,62
; Copyright 2012, Sinclair R.F., Inc. |
; |
; Multi-byte arithmetic |
|
; Notation: Multi-byte values on the stack are xx[n] where n=0 is the least |
; significant byte of the value |
|
.function add_u16_u8__u16 ; ( u0[0] u0[1] u1[0] - us[0] us[1] ) |
swap >r +uu r> + |
.return |
|
.function add_u16_u8__u24 ; ( u0[0] u0[1] u1[0] - us[0] us[1] us[2] ) |
swap >r +uu r> +uu |
.return |
|
.function add_u16_u16__u16 ; ( u0[0] u0[1] u1[0] u1[1] - us[0] us[1] ) |
>r .call(add_u16_u8__u16) r> + |
.return |
|
.function add_u16_u16__u24 ; ( u0[0] u0[1] u1[0] u1[1] - us[0] us[1] us[2] ) |
>r .call(add_u16_u8__u24) r> .call(add_u16_u8__u16) |
.return |
|
.function add_u24_u8__u24 ; ( u0[0] u0[1] u0[2] u1[0] - us[0] us[1] us[2] ) |
swap >r .call(add_u16_u8__u24) r> + |
.return |
|
.function add_u24_u8__u32 ; ( u0[0] u0[1] u0[2] u1[0] - us[0] us[1] us[2] u[3] ) |
swap >r .call(add_u16_u8__u24) r> +uu |
.return |
|
.function add_u24_u16__u24 ; ( u0[0] u0[1] u0[2] u1[0] u1[1] - us[0] us[1] us[2] ) |
>r .call(add_u24_u8__u24) r> .call(add_u16_u8__u16) |
.return |
|
.function add_u24_u16__u32 ; ( u0[0] u0[1] u0[2] u1[0] u1[1] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u24_u8__u32) r> .call(add_u24_u8__u24) |
.return |
|
.function add_u24_u24__u24 ; ( u0[0] u0[1] u0[2] u1[0] u1[1] u1[2] - us[0] us[1] us[2] ) |
>r .call(add_u24_u16__u24) r> + |
.return |
|
.function add_u24_u24__u32 ; ( u0[0] u0[1] u0[2] u1[0] u1[1] u1[2] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u24_u16__u32) r> .call(add_u16_u8__u16) |
.return |
|
.function add_u32_u8__u32 ; ( u0[0] u0[1] u0[2] u0[3] u1[0] - us[0] us[1] us[2] us[3] ) |
swap >r .call(add_u24_u8__u32) r> + |
.return |
|
.function add_u32_u16__u32 ; ( u0[0] u0[1] u0[2] u0[3] u1[0] u1[1] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u32_u8__u32) r> .call(add_u24_u8__u24) |
.return |
|
.function add_u32_u24__u32 ; ( u0[0] u0[1] u0[2] u0[3] u1[0] u1[1] u1[2] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u32_u16__u32) r> .call(add_u16_u8__u16) |
.return |
|
.function add_u32_u32__u32 ; ( u0[0] u0[1] u0[2] u0[3] u1[0] u1[1] u1[2] u1[3] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u32_u24__u32) r> + |
.return |
/lib/9x8/tb/.gitignore
1,6 → 1,5
ssbcc |
tb |
uc.9x8 |
uc.9x8-meta |
uc.v |
*.mem |
/lib/9x8/tb/math/tb.gtkw
0,0 → 1,37
[*] |
[*] GTKWave Analyzer v3.3.42 (w)1999-2012 BSI |
[*] Mon Mar 24 17:27:25 2014 |
[*] |
[dumpfile] "/home/rsinclair/Projects/SSBCC/lib/9x8/tb/math/tb.vcd" |
[dumpfile_mtime] "Mon Mar 24 17:22:21 2014" |
[dumpfile_size] 54584 |
[savefile] "/home/rsinclair/Projects/SSBCC/lib/9x8/tb/math/tb.gtkw" |
[timestart] 593900 |
[size] 1920 1171 |
[pos] -1 -1 |
*-15.400721 750000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 |
[treeopen] tb. |
[sst_width] 205 |
[signals_width] 223 |
[sst_expanded] 1 |
[sst_vpaned_height] 353 |
@28 |
tb.inst_uc.i_clk |
tb.inst_uc.i_rst |
@23 |
tb.inst_uc.s_R_stack_ptr[4:0] |
@22 |
>10000 |
tb.inst_uc.s_PC[9:0] |
>10000 |
tb.inst_uc.s_opcode[8:0] |
@820 |
>0 |
tb.inst_uc.s_opcode_name[23:0] |
@22 |
tb.inst_uc.s_R[9:0] |
tb.inst_uc.s_T[7:0] |
tb.inst_uc.s_N[7:0] |
tb.inst_uc.s_Np_stack_ptr[6:0] |
[pattern_trace] 1 |
[pattern_trace] 0 |
/lib/9x8/tb/math/run
0,0 → 1,18
#!/bin/bash |
# Copyright 2013, Sinclair R.F., Inc. |
# Run the test benches for the libraries. |
|
NAME="math"; |
|
rm --force ssbcc; |
ln -s ../../../../ssbcc; |
|
./ssbcc -q -P monitor_stack --display-opcode uc.9x8 || { echo "FATAL ERROR testing ${NAME}" > /dev/stderr; exit 1; } |
iverilog -o tb tb.v uc.v || exit 1; |
if [ -n "`./tb | gawk -f tb.awk`" ]; then |
echo "${NAME} failed" > /dev/stderr; |
exit 1; |
fi |
echo "Passed: ${NAME}"; |
|
#rm --force ssbcc uc.9x8-meta uc.v tb; |
lib/9x8/tb/math/run
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lib/9x8/tb/math/tb.awk
===================================================================
--- lib/9x8/tb/math/tb.awk (nonexistent)
+++ lib/9x8/tb/math/tb.awk (revision 4)
@@ -0,0 +1,8 @@
+/^VCD/{ next; }
+{
+ a=strtonum("0x" $1);
+ b=strtonum("0x" $3);
+ c=strtonum("0x" $5);
+ if (c != a + b)
+ print $0;
+}
lib/9x8/tb/math/tb.awk
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: lib/9x8/tb/math/uc.s
===================================================================
--- lib/9x8/tb/math/uc.s (nonexistent)
+++ lib/9x8/tb/math/uc.s (revision 4)
@@ -0,0 +1,146 @@
+; Copyright 2014, Sinclair R.F., Inc.
+; Test bench for ../../math.s
+
+.include math.s
+
+.macro push16
+.macro push24
+.macro push32
+
+.main
+
+ ; Test u8 + u8 ==> u16
+ 0x7F 0x80
+ 0x7F 0x81
+ 0x80 0x7F
+ 0x80 0x80
+ 0x80 0x81
+ 0xFF 0x00
+ 0xFF 0x01
+ 0xFF 0x02
+ 0xFF 0xFE
+ 0xFF 0xFF
+ ${10-1} :loop__u8_u8_u16 >r
+ .call(out8,over)
+ .call(out8,dup)
+ .call(math__add_u8_u8_u16) .call(out16)
+ .outstrobe(O_VALUE_DONE)
+ r> .jumpc(loop__u8_u8_u16,1-) drop
+
+ .push16(0x007F) 0x80
+ .push16(0x007F) 0x81
+ .push16(0x0080) 0x7F
+ .push16(0x0080) 0x80
+ .push16(0x0080) 0x81
+ .push16(0x00FF) 0x00
+ .push16(0x00FF) 0x01
+ .push16(0x00FF) 0x02
+ .push16(0x00FF) 0xFE
+ .push16(0x00FF) 0xFF
+ .push16(0x017F) 0x80
+ .push16(0x017F) 0x81
+ .push16(0x0180) 0x7F
+ .push16(0x0180) 0x80
+ .push16(0x0180) 0x81
+ .push16(0x01FF) 0x00
+ .push16(0x01FF) 0x01
+ .push16(0x01FF) 0x02
+ .push16(0x01FF) 0xFE
+ .push16(0x01FF) 0xFF
+ ${20-1} :loop__u16_u8_u16 >r
+ >r over .call(out16,over)
+ r> .call(out8,dup)
+ .call(math__add_u16_u8_u16) .call(out16)
+ .outstrobe(O_VALUE_DONE)
+ r> .jumpc(loop__u16_u8_u16,1-) drop
+
+ .push24(0x0001FF) 0xFF
+ ${1-1} :loop__u24_u8_u24 >r
+ >r .call(preserve_out24) r>
+ .call(out8,dup)
+ .call(math__add_u24_u8_u24)
+ .call(out24)
+ .outstrobe(O_VALUE_DONE)
+ r> .jumpc(loop__u24_u8_u24,1-) drop
+
+ .push24(0x0001FF) 0xFF
+ ${1-1} :loop__u24_u8_u32 >r
+ >r .call(preserve_out24) r>
+ .call(out8,dup)
+ .call(math__add_u24_u8_u32)
+ .call(out32)
+ .outstrobe(O_VALUE_DONE)
+ r> .jumpc(loop__u24_u8_u32,1-) drop
+
+ .push32(0x00800000) 0xFF
+ ${1-1} :loop__u32_u8_u32 >r
+ >r .call(preserve_out32) r>
+ .call(out8,dup)
+ .call(math__add_u32_u8_u32)
+ .call(out32)
+ .outstrobe(O_VALUE_DONE)
+ r> .jumpc(loop__u32_u8_u32,1-) drop
+
+ .push32(${0x00800000+0*1280*960*4}) .push24(${1280*960*4})
+ .push32(${0x00800000+1*1280*960*4}) .push24(${1280*960*4})
+ .push32(${0x00800000+2*1280*960*4}) .push24(${1280*960*4})
+ .push32(${0x00800000+3*1280*960*4}) .push24(${1280*960*4})
+ .push32(${0x00800000+4*1280*960*4}) .push24(${1280*960*4})
+ ${5-1} :loop__u32_u24_u32 >r
+ >r >r >r .call(preserve_out32) r> r> r>
+ .call(preserve_out24)
+ .call(math__add_u32_u24_u32)
+ .call(out32)
+ .outstrobe(O_VALUE_DONE)
+ r> .jumpc(loop__u32_u24_u32,1-) drop
+
+ .push32(${0x00800000+0*1280*960*4}) .push32(${1280*960*4})
+ .push32(${0x00800000+1*1280*960*4}) .push32(${1280*960*4})
+ .push32(${0x00800000+2*1280*960*4}) .push32(${1280*960*4})
+ .push32(${0x00800000+3*1280*960*4}) .push32(${1280*960*4})
+ .push32(${0x00800000+4*1280*960*4}) .push32(${1280*960*4})
+ ${5-1} :loop__u32_u32_u32 >r
+ >r >r >r >r .call(preserve_out32) r> r> r> r>
+ .call(preserve_out32)
+ .call(math__add_u32_u32_u32)
+ .call(out32)
+ .outstrobe(O_VALUE_DONE)
+ r> .jumpc(loop__u32_u32_u32,1-) drop
+
+ ; terminate and wait forever
+ .outstrobe(O_TERMINATE) :infinite .jump(infinite)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Routines to output results.
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+.function preserve_out24
+ 0 .outport(O_VALUE)
+ .outport(O_VALUE,>r)
+ .outport(O_VALUE,>r)
+ O_VALUE outport
+ r> r>
+ .return
+
+.function preserve_out32
+ .outport(O_VALUE,>r)
+ .outport(O_VALUE,>r)
+ .outport(O_VALUE,>r)
+ O_VALUE outport
+ r> r> r>
+ .return
+
+.function out8
+ 0 0 0 .call(out32) .return
+
+.function out16
+ 0 0 .call(out32) .return
+
+.function out24
+ 0 .call(out32) .return
+
+.function out32
+ ${4-1} :loop swap .outport(O_VALUE) .jumpc(loop,1-) drop
+ .return
Index: lib/9x8/tb/math/tb.v
===================================================================
--- lib/9x8/tb/math/tb.v (nonexistent)
+++ lib/9x8/tb/math/tb.v (revision 4)
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ *
+ * Copyright 2014, Sinclair R.F., Inc.
+ *
+ * Test bench for the core/9x8 math library.
+ *
+ ******************************************************************************/
+
+`timescale 1ns/1ps
+
+module tb;
+
+reg s_clk = 1'b1;
+always @ (s_clk)
+ s_clk <= #5 ~s_clk;
+
+reg s_rst = 1'b1;
+initial begin
+ repeat (5) @ (posedge s_clk)
+ s_rst <= 1'b0;
+end
+
+wire [95:0] s_value;
+wire s_value_done;
+wire s_terminate;
+uc inst_uc(
+ // synchronous reset and processor clock
+ .i_rst (s_rst),
+ .i_clk (s_clk),
+ // 8-bit test values
+ .o_value (s_value),
+ .o_value_done (s_value_done),
+ // termination strobe
+ .o_terminate (s_terminate)
+);
+
+always @ (posedge s_value_done)
+ $display("%08h + %08h = %08h", s_value[64+:32], s_value[32+:32], s_value[0+:32]);
+
+always @ (posedge s_terminate)
+ $finish;
+
+initial begin
+ $dumpfile("tb.vcd");
+ $dumpvars();
+end
+
+endmodule
lib/9x8/tb/math/tb.v
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: lib/9x8/tb/math/uc.9x8
===================================================================
--- lib/9x8/tb/math/uc.9x8 (nonexistent)
+++ lib/9x8/tb/math/uc.9x8 (revision 4)
@@ -0,0 +1,21 @@
+# Copyright 2014, Sinclair R.F., Inc.
+# Test bench for the math library.
+
+ARCHITECTURE core/9x8 Verilog
+
+INSTRUCTION 1024
+DATA_STACK 128
+RETURN_STACK 32
+
+PORTCOMMENT 32-bit addition result
+PERIPHERAL big_outport outport=O_VALUE \
+ outsignal=o_value \
+ width=96
+OUTPORT strobe o_value_done \
+ O_VALUE_DONE
+
+PORTCOMMENT termination strobe
+OUTPORT strobe o_terminate \
+ O_TERMINATE
+
+ASSEMBLY uc.s
Index: lib/9x8/tb/char/uc.s
===================================================================
--- lib/9x8/tb/char/uc.s (revision 3)
+++ lib/9x8/tb/char/uc.s (revision 4)
@@ -1,5 +1,5 @@
; Copyright 2013, Sinclair R.F., Inc.
-; Test bench for ../char.s
+; Test bench for ../../char.s
.include char.s
/lib/9x8/tb/char/uc.9x8
0,0 → 1,16
# Copyright 2013, Sinclair R.F., Inc. |
# Test bench for the math libraries. |
|
ARCHITECTURE core/9x8 Verilog |
|
INSTRUCTION 1024 |
DATA_STACK 32 |
RETURN_STACK 32 |
|
PORTCOMMENT 8-bit test values |
OUTPORT 8-bit,strobe o_value,o_value_wr O_VALUE |
|
PORTCOMMENT termination strobe |
OUTPORT strobe o_terminate_str O_TERMINATE |
|
ASSEMBLY uc.s |
/lib/9x8/tb/cmp_8bit_uu/uc.s
1,5 → 1,5
; Copyright 2013, Sinclair R.F., Inc. |
; Test bench for ../cmp_8bit_uu.s |
; Test bench for ../../cmp_8bit_uu.s |
|
.include cmp_8bit_uu.s |
|
/lib/9x8/tb/cmp_8bit_uu/uc.9x8
1,5 → 1,5
# Copyright 2013, Sinclair R.F., Inc. |
# Test bench for the math libraries. |
# Test bench for the icomparison math library. |
|
ARCHITECTURE core/9x8 Verilog |
|
/lib/9x8/math.s
1,62 → 1,60
; Copyright 2012, Sinclair R.F., Inc. |
; Copyright 2014, Sinclair R.F., Inc. |
; |
; Multi-byte arithmetic |
; Unsigned arithmetic operations. |
|
; Notation: Multi-byte values on the stack are xx[n] where n=0 is the least |
; significant byte of the value |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
; Add two unsigned 8-bit values to produce an unsigned 16-bit value. |
; Method: Calculate the sum of the msb of the two raw values and the msb of the |
; sums of the 7 lsbs of the two values to get the msb of the sum and |
; the lsb of the MSB of the 16-bit sum. |
; 36 instructions |
; |
; ( u1 u2 - (u1+u2)_LSB (u1+u2)_MSB ) |
.function math__add_u8_u8_u16 |
; and the two 7 lsbs and put the 7 lsb of that sum on the return stack |
over 0x7F & over 0x7F & + dup 0x7F & >r |
; add the msb of the sum of the 7 lsbs and the two inputs |
0x80 & <<msb swap 0x80 & <<msb + swap 0x80 & <<msb + |
; construct the MSB of the sum as bit 1 of the sums of the msbs |
dup 0>> swap |
; set the msb of the LSB if the lsb of the sum of the msbs is non-zero |
0x01 & 0<> 0x80 & r> or |
; swap the orders so that the MSB is on the top of the data stack |
.return(swap) |
|
.function add_u16_u8__u16 ; ( u0[0] u0[1] u1[0] - us[0] us[1] ) |
swap >r +uu r> + |
.return |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; miscellaneous unsigned addition operations |
|
.function add_u16_u8__u24 ; ( u0[0] u0[1] u1[0] - us[0] us[1] us[2] ) |
swap >r +uu r> +uu |
.return |
.function math__add_u16_u8_u16 |
swap >r .call(math__add_u8_u8_u16) r> .return(+) |
|
.function add_u16_u16__u16 ; ( u0[0] u0[1] u1[0] u1[1] - us[0] us[1] ) |
>r .call(add_u16_u8__u16) r> + |
.return |
.function math__add_u16_u8_u24 |
swap >r .call(math__add_u8_u8_u16) r> .call(math__add_u8_u8_u16) .return |
|
.function add_u16_u16__u24 ; ( u0[0] u0[1] u1[0] u1[1] - us[0] us[1] us[2] ) |
>r .call(add_u16_u8__u24) r> .call(add_u16_u8__u16) |
.return |
.function math__add_u24_u8_u24 |
swap >r .call(math__add_u16_u8_u24) |
r> .return(+) |
|
.function add_u24_u8__u24 ; ( u0[0] u0[1] u0[2] u1[0] - us[0] us[1] us[2] ) |
swap >r .call(add_u16_u8__u24) r> + |
.return |
.function math__add_u24_u8_u32 |
swap >r .call(math__add_u16_u8_u24) |
r> .call(math__add_u8_u8_u16) |
.return |
|
.function add_u24_u8__u32 ; ( u0[0] u0[1] u0[2] u1[0] - us[0] us[1] us[2] u[3] ) |
swap >r .call(add_u16_u8__u24) r> +uu |
.return |
.function math__add_u32_u8_u32 |
swap >r .call(math__add_u24_u8_u32) |
r> .return(+) |
|
.function add_u24_u16__u24 ; ( u0[0] u0[1] u0[2] u1[0] u1[1] - us[0] us[1] us[2] ) |
>r .call(add_u24_u8__u24) r> .call(add_u16_u8__u16) |
.return |
.function math__add_u32_u16_u32 |
>r .call(math__add_u32_u8_u32) |
r> .call(math__add_u24_u8_u24) |
.return |
|
.function add_u24_u16__u32 ; ( u0[0] u0[1] u0[2] u1[0] u1[1] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u24_u8__u32) r> .call(add_u24_u8__u24) |
.return |
.function math__add_u32_u24_u32 |
>r .call(math__add_u32_u16_u32) |
r> .call(math__add_u16_u8_u16) |
.return |
|
.function add_u24_u24__u24 ; ( u0[0] u0[1] u0[2] u1[0] u1[1] u1[2] - us[0] us[1] us[2] ) |
>r .call(add_u24_u16__u24) r> + |
.return |
|
.function add_u24_u24__u32 ; ( u0[0] u0[1] u0[2] u1[0] u1[1] u1[2] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u24_u16__u32) r> .call(add_u16_u8__u16) |
.return |
|
.function add_u32_u8__u32 ; ( u0[0] u0[1] u0[2] u0[3] u1[0] - us[0] us[1] us[2] us[3] ) |
swap >r .call(add_u24_u8__u32) r> + |
.return |
|
.function add_u32_u16__u32 ; ( u0[0] u0[1] u0[2] u0[3] u1[0] u1[1] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u32_u8__u32) r> .call(add_u24_u8__u24) |
.return |
|
.function add_u32_u24__u32 ; ( u0[0] u0[1] u0[2] u0[3] u1[0] u1[1] u1[2] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u32_u16__u32) r> .call(add_u16_u8__u16) |
.return |
|
.function add_u32_u32__u32 ; ( u0[0] u0[1] u0[2] u0[3] u1[0] u1[1] u1[2] u1[3] - us[0] us[1] us[2] us[3] ) |
>r .call(add_u32_u24__u32) r> + |
.return |
.function math__add_u32_u32_u32 |
>r .call(math__add_u32_u24_u32) |
r> .return(+) |
/core/9x8/macros/fetchvector.py
1,5 → 1,7
# Copyright 2014, Sinclair R.F., Inc. |
|
from asmDef import AsmException |
|
def fetchvector(ad): |
""" |
Built-in macro to move multiple bytes from memory to the data stack. The byte |
16,7 → 18,10
""" |
|
def length(ad,argument): |
return int(argument[1]['value']) + 1; |
N = ad.Emit_IntegerValue(argument[1]); |
if not (N > 0): |
raise asmDef.AsmException('Vector length must be positive at %s' % argument[1]['loc']); |
return N+1; |
|
# Add the macro to the list of recognized macros. |
ad.AddMacro('.fetchvector', length, [ |
28,9 → 33,11
def emitFunction(ad,fp,argument): |
variableName = argument[0]['value']; |
(addr,ixBank,bankName) = ad.Emit_GetAddrAndBank(variableName); |
N = int(argument[1]['value']); |
ad.EmitPush(fp,addr+N-1,'%s+%d' % (variableName,N-1)); |
N = ad.Emit_IntegerValue(argument[1]); |
offsetString = '%s-1' % argument[1]['value'] if type(argument[0]['value']) == str else '%d-1' % N; |
ad.EmitPush(fp,addr+N-1,'%s+%s' % (variableName,offsetString)); |
for dummy in range(N-1): |
ad.EmitOpcode(fp,ad.specialInstructions['fetch-'] | ixBank,'fetch- '+bankName); |
ad.EmitOpcode(fp,ad.specialInstructions['fetch'] | ixBank,'fetch '+bankName); |
|
ad.EmitFunction['.fetchvector'] = emitFunction; |
/core/9x8/ssbccGenVerilog.py
752,6 → 752,7
signalType = signal[2]; |
signalInit = '%d\'d0' % signalWidth if len(signal)==3 else signal[3]; |
if signalType == 'data': |
fp.write('initial %s = %s;\n' % (signalName,signalInit,)); |
if bitWidth > 0: |
bitName += ', '; |
bitInit += ', ' |
777,6 → 778,7
if signalType == 'data': |
pass; |
elif signalType == 'strobe': |
fp.write('initial %s = 1\'b0;\n' % signalName); |
fp.write('always @ (posedge i_clk)\n'); |
fp.write(' if (i_rst)\n'); |
fp.write(' %s <= 1\'b0;\n' % signalName); |
/core/9x8/asmDef_9x8.py
902,6 → 902,27
self.emitLabelList = ''; |
return name; |
|
def Emit_IntegerValue(self,token): |
""" |
Return the integer value associated with a constant or a numeric expression. |
""" |
if token['type'] == 'value': |
v = token['value']; |
elif token['type'] == 'symbol': |
name = token['value']; |
if not self.IsSymbol(name): |
raise asmDef.AsmException('Symbol "%s" not recognized at %s' % (token['value'],token['loc'],)); |
ix = self.symbols['list'].index(name); |
v = self.symbols['body'][ix]; |
if len(v) != 1: |
raise asmDef.AsmException('Argument can only be one value at %s' % token['loc']); |
v = v[0]; |
else: |
raise asmDef.AsmException('Argument "%s" of type "%s" not recognized at %s' % (token['value'],token['type'],token['loc'],)); |
if type(v) != int: |
raise Exception('Program Bug -- value should be an "int"'); |
return v; |
|
# |
# Utilities to write single instructions to the metacode file. |
# |
1272,7 → 1293,7
['','symbol'], |
['drop','instruction','singlemacro','singlevalue','symbol'] |
]); |
self.AddMacro('.return', 2, [ ['nop','instruction','singlevalue','symbol'] ]); |
self.AddMacro('.return', 2, [ ['nop','instruction','singlemacro','singlevalue','symbol'] ]); |
self.AddMacro('.store', 1, [ ['','symbol'] ]); |
self.AddMacro('.store+', 1, [ ['','symbol'] ]); |
self.AddMacro('.store-', 1, [ ['','symbol'] ]); |
/core/9x8/peripherals/vivado_AXI4_Lite_Bus.py
45,6 → 45,8
ipx::remove_bus_interface {o_@BASEPORTNAME@} [ipx::current_core] |
ipx::remove_bus_interface {i_@BASEPORTNAME@_signal_reset} [ipx::current_core] |
ipx::remove_bus_interface {i_@BASEPORTNAME@_signal_clock} [ipx::current_core] |
ipx::remove_memory_map {i_@BASEPORTNAME@} [ipx::current_core] |
ipx::remove_memory_map {o_@BASEPORTNAME@} [ipx::current_core] |
|
# Create the AXI4-Lite port. |
ipx::add_bus_interface {@BASEPORTNAME@} [ipx::current_core] |
88,10 → 90,14
body += """ |
# Fix the address space |
ipx::add_address_space {@BASEPORTNAME@} [ipx::current_core] |
set_property master_address_space_ref {@BASEPORTNAME@} [ipx::get_bus_interface @BASEPORTNAME@ [ipx::current_core]] |
"""; |
if mode == 'master': |
body += """set_property master_address_space_ref {@BASEPORTNAME@} [ipx::get_bus_interface @BASEPORTNAME@ [ipx::current_core]] |
set_property range {@ADDR_WIDTH@} [ipx::get_address_space @BASEPORTNAME@ [ipx::current_core]] |
set_property width {32} [ipx::get_address_space @BASEPORTNAME@ [ipx::current_core]] |
"""; |
else: |
body += "ipx::remove_address_space {@BASEPORTNAME@} [ipx::current_core]\n"; |
|
body += """ |
# Fix the reset port definition |
/core/9x8/peripherals/AXI4_Lite_Slave_DualPortRAM.v
26,6 → 26,9
reg s__axi_got_wdata = 1'b0; |
reg s__axi_got_raddr = 1'b0; |
reg [L__NBITS_SIZE-1:2] s__axi_addr = {(L__NBITS_SIZE-2){1'b0}}; |
initial o_awready = 1'b0; |
initial o_wready = 1'b0; |
initial o_arready = 1'b0; |
always @ (posedge i_aclk) |
if (~i_aresetn) begin |
s__axi_idle <= 1'b1; |
33,6 → 36,9
s__axi_got_wdata <= 1'b0; |
s__axi_got_raddr <= 1'b0; |
s__axi_addr <= {(L__NBITS_SIZE-2){1'b0}}; |
o_awready <= 1'b0; |
o_wready <= 1'b0; |
o_arready <= 1'b0; |
end else begin |
s__axi_idle <= s__axi_idle; |
s__axi_got_waddr <= s__axi_got_waddr; |
75,9 → 81,22
initial o_bvalid = 1'b0; |
always @ (*) |
o_bvalid = s__axi_got_wdata; |
reg s__axi_arready_s = 1'b0; |
always @ (posedge i_aclk) |
if (~i_aresetn) |
s__axi_arready_s <= 1'b0; |
else |
s__axi_arready_s <= o_arready; |
initial o_rvalid = 1'b0; |
always @ (s__axi_got_raddr) |
o_rvalid = s__axi_got_raddr; |
always @ (posedge i_aclk) |
if (~i_aresetn) |
o_rvalid <= 1'b0; |
else if (s__axi_arready_s) |
o_rvalid <= 1'b1; |
else if (i_rready) |
o_rvalid <= 1'b0; |
else |
o_rvalid <= o_rvalid; |
// signals common to both memory architectures |
reg [L__NBITS_SIZE-1:2] s__axi_addr_s = {(L__NBITS_SIZE-2){1'b0}}; |
always @ (posedge i_aclk) |
/core/9x8/peripherals/tb/AXI4_Lite_Slave_DualPortRAM/master.gtkw
0,0 → 1,50
[*] |
[*] GTKWave Analyzer v3.3.42 (w)1999-2012 BSI |
[*] Sun Mar 23 13:48:13 2014 |
[*] |
[dumpfile] "/home/rsinclair/Projects/SSBCC/core/9x8/peripherals/tb/AXI4_Lite_Slave_DualPortRAM/tb.vcd" |
[dumpfile_mtime] "Sun Mar 23 12:59:00 2014" |
[dumpfile_size] 869113 |
[savefile] "/home/rsinclair/Projects/SSBCC/core/9x8/peripherals/tb/AXI4_Lite_Slave_DualPortRAM/master.gtkw" |
[timestart] 20022900 |
[size] 1920 1171 |
[pos] -1 -1 |
*-16.801830 20420000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 |
[treeopen] tb. |
[treeopen] tb.uut. |
[sst_width] 205 |
[signals_width] 276 |
[sst_expanded] 1 |
[sst_vpaned_height] 353 |
@28 |
tb.uut.i_axi_lite_aclk |
tb.uut.i_axi_lite_aresetn |
@200 |
-write side |
@22 |
tb.uut.i_axi_lite_awaddr[6:0] |
tb.uut.i_axi_lite_wdata[31:0] |
tb.uut.i_axi_lite_wstrb[3:0] |
@28 |
tb.uut.o_axi_lite_awready |
tb.uut.i_axi_lite_awvalid |
tb.uut.o_axi_lite_wready |
tb.uut.i_axi_lite_wvalid |
tb.uut.i_axi_lite_bready |
tb.uut.o_axi_lite_bvalid |
tb.uut.o_axi_lite_bresp[1:0] |
@200 |
-read side |
@22 |
tb.uut.i_axi_lite_araddr[6:0] |
@29 |
tb.uut.o_axi_lite_arready |
@28 |
tb.uut.i_axi_lite_arvalid |
tb.uut.i_axi_lite_rready |
tb.uut.o_axi_lite_rvalid |
tb.uut.o_axi_lite_rresp[1:0] |
@22 |
tb.uut.o_axi_lite_rdata[31:0] |
[pattern_trace] 1 |
[pattern_trace] 0 |
/core/9x8/peripherals/tb/AXI4_Lite_Slave_DualPortRAM/tb.v
128,6 → 128,7
end |
|
// Initiate reads and indicate their termination |
localparam S_INIT_RREADY = 1'b1; // observed Xilinx behavior -- always high |
initial s_rd_done = 1'b0; |
reg [1:0] s_rd_acks = 2'b00; |
reg s_arvalid = 1'b0; |
137,7 → 138,7
always @ (posedge s_aclk) begin |
s_rd_done <= 1'b0; |
s_rd_acks <= s_rd_acks; |
s_rready <= 1'b0; |
s_rready <= S_INIT_RREADY; |
if (s_rd_acks == 2'b11) begin |
s_rd_done <= 1'b1; |
s_rd_acks <= 2'b00; |
205,4 → 206,9
if (s_done) |
$finish; |
|
//initial begin |
// $dumpfile("tb.vcd"); |
// $dumpvars(); |
//end |
|
endmodule |
/core/9x8/peripherals/AXI4_Lite_Slave_DualPortRAM.py
46,7 → 46,7
optionally specifies using an 8-bit RAM for the dual-port memory instantiation |
Note: This is the default |
ram32 |
optionally specifies using a 32-bit RAM for the dual-port memrory instantiation |
optionally specifies using a 32-bit RAM for the dual-port memory instantiation |
Note: This is required for Vivado 2013.3.\n |
Vivado Users: |
The peripheral creates a TCL script to facilitate turning the micro |
107,6 → 107,10
if not re.match(r'[1-9]\d*$', y): |
raise SSBCCException('localparam must be a numeric constant, not "%s", to be used in "size=%s" at %s' % (y,x,loc,)); |
y = int(y); |
elif re.match(r'C_\w+$',x): |
if not config.IsConstant(x): |
raise SSBCCException('"size=%s" is not a constant at %s' % (x,loc,)); |
y = int(config.constants[x]); |
elif re.match(r'[1-9]\d*$',x): |
y = int(x); |
else: |
/ssbccConfig.py
331,6 → 331,15
else: |
return False; |
|
def IsConstant(self,name): |
""" |
Indicate whether or not the specified symbol is a recognized constant. |
""" |
if re.match(r'C_\w+$',name) and name in self.constants: |
return True; |
else: |
return False; |
|
def IsMemory(self,name): |
""" |
Indicate whether or not the specified symbol is the name of a memory. |
341,7 → 350,7
""" |
Indicate whether or not the specified symbol is the name of a parameter. |
""" |
if re.match(r'[GL]_\w+',name) and name in self.symbols: |
if re.match(r'[GL]_\w+$',name) and name in self.symbols: |
return True; |
else: |
return False; |
/README
1,10 → 1,16
SSBCC.9x8 is a free Small Stack-Based Computer Compiler with a 9-bit opcode, |
8-bit data core. It creates vendor-independent, high-speed, low fabric |
utilization micro controllers for FPGAs. It has been used in Spartan-3A, |
Spartan-6, Virtex-6, and Artix-7 FPGAs and has been built for Altera, Lattice, |
and other Xilinx devices. It is faster and usually smaller than vendor provided |
processors. |
8-bit data core designed to facilitate FPGA HDL development. |
|
The primary design criteria are: |
- high speed (to avoid timing issues) |
- low fabric utilization |
- vendor independent |
- development tools available for all operating systems |
|
It has been used in Spartan-3A, Spartan-6, Virtex-6, and Artix-7 FPGAs and has |
been built for Altera, Lattice, and other Xilinx devices. It is faster and |
usually smaller than vendor provided processors. |
|
The compiler takes an architecture file that describes the micro controller |
memory spaces, inputs and outputs, and peripherals and which specifies the HDL |
language and source assembly. It generates a single HDL module implementing |
11,6 → 17,19
the entire micro controller. No user-written HDL is required to instantiate |
I/Os, program memory, etc. |
|
The features are: |
- high speed, low fabric utilization |
- vendor-independent Verilog output with a VHDL package file |
- simple Forth-like assembly language (41 instructions) |
- single cycle instruction execution |
- automatic generation of I/O ports |
- configurable instruction, data stack, return stack, and memory utilization |
- extensible set of peripherals (I2C busses, UARTs, AXI4-Lite busses, etc.) |
- extensible set of macros |
- memory initialization file to facilitate code development without rebuilds |
- simulation diagnostics to facilitate identifying code errors |
- conditionally included I/Os and peripherals, functions, and assembly code |
|
SSBCC has been used for the following projects: |
- operate a media translator from a parallel camera interface to an OMAP GPMC |
interface, detect and report bus errors and hardware errors, and act as an |
19,7 → 38,9
- operate and monitor the Artix-7 fabric in a Zynq system using AXI4-Lite |
master and slave buses, I2C buses for timing-critical voltage measurements |
|
The only external tool required is Python 2.7. |
|
|
DESCRIPTION |
================================================================================ |
|
28,18 → 49,18
output ports; RAM and ROM types and sizes; and peripherals. |
|
The instructions are all single-cycle. The instructions include |
- pushing an 8-bit value onto the data stack |
- arithmetic operations: addition, subtraction, increment, and decrement |
- bit-wise logical operations: and, or, and exclusive or |
- rotations |
- logical operations: 0=, 0<>, -1=, -1<> |
- Forth-like data stack operations: dup, over, swap, drop, nip |
- Forth-like return stack operations: >r, r>, r@ |
- input and output port operations |
- memory read and write with optional address post increment and post decrement |
- jumps and conditional jumps |
- calls and conditional calls |
- function return |
- 4 arithmetic instructions: addition, subtraction, increment, and decrement |
- 3 bit-wise logical instructions: and, or, and exclusive or |
- 7 shift and rotation instructions: <<0, <<1, 0>>, 1>>, <<msb, >>msb, and >>lsb |
- 4 logical instructions: 0=, 0<>, -1=, -1<> |
- 6 Forth-like data stack instructions: drop, dup, nip, over, push, swap |
- 3 Forth-like return stack instructions: >r, r>, r@ |
- 2 input and output |
- 6 memory read and write with optional address post increment and post decrement |
- 2 jump and conditional jump |
- 2 call and conditional call |
- 1 function return |
- 1 nop |
|
The 9x8 address space is up to 8K. This is achieved by pushing the 8 lsb of the |
target address onto the data stack immediately before the jump or call |
51,9 → 72,9
Up to four banks of memory, either RAM or ROM, are available. Each of these can |
be up to 256 bytes long, providing a total of up to 1 kB of memory. |
|
The assembly language is Forth-like. Macros are used to encode the jump and |
call instructions and to encode the 2-bit memory bank index in memory store and |
fetch instructions. |
The assembly language is Forth-like. Built-in macros are used to encode the |
jump and call instructions and to encode the 2-bit memory bank index in memory |
store and fetch instructions. |
|
The computer compiler and assembler are written in Python 2.7. Peripherals are |
implemented by Python modules which generate the I/O ports and the peripheral |
65,11 → 86,7
The computer compiler and assembler are fully functional and there are no known |
bugs. |
|
Features and peripherals are still being added and the documentation is |
incomplete. The output HDL is currently restricted to Verilog although a VHDL |
package file is automatically generated by the computer compiler. |
|
|
SPEED AND RESOURCE UTILIZATION |
================================================================================ |
These device speed and resource utilization results are copied from the build |
97,7 → 114,7
numbers do provide is an estimate of the amount of slack available. For |
example, you can't realistically expect to get 110 MHz from a processor that, |
under ideal conditions, routes and places at 125 MHz, but you can with a |
processor that synthesizes at more than 150 MHz. |
processor that synthesizes at 150 MHz. |
|
|
EXAMPLE: |
276,9 → 293,8
|
C"Hello World!" |
|
In this case the number of characters, 12 in this example, in the string is |
pushed onto the data stack after the 'H', i.e., the instruction sequence would |
be |
In this case the number of characters, 12, in the string is pushed onto the data |
stack after the 'H', i.e., the instruction sequence would be |
|
'!' 'd' 'l' ... 'e' 'H' 12 |
|
1058,8 → 1074,13
The following macros are provided in macros/9x8: |
.push16(v) push the 16-bit (2-byte) value "v" onto the data stack with the |
MSB at the top of the data stack |
.push24(v) push the 24-bit (3-byte) value "v" onto the data stack with the |
MSB at the top of the data stack |
.push32(v) push the 32-bit (4-byte) value "v" onto the data stack with the |
MSB at the top of the data stack |
.pushByte(v,ix) |
push the ix'th byte of v onto the data stack |
Note: ix=0 designates the LSB |
|
Directories are searched in the following order for macros: |
. |
1072,7 → 1093,8
on the list provided when the macro is registered by the "AddMacro" method, but |
additional type checking is often warranted by the macro "emitFunction" which |
emits the actual assembly code. The ".fetchvector" and ".storevector" macros |
demonstrates how to design variable-length macros. |
demonstrates how to design variable-length macros. Several macros in |
core/9x8/macros illustrate designing macros with optional arguments. |
|
It is not an error to repeat the ".macro MACRO_NAME" directive for user-defined |
macros. The assembler will issue a fatal error if a user-defined macro |
1198,6 → 1220,10
MISCELLANEOUS |
================================================================================ |
|
Features and peripherals are still being added and the documentation is |
incomplete. The output HDL is currently restricted to Verilog although a VHDL |
package file is automatically generated by the computer compiler. |
|
The "INVERT_RESET" configuration command is used to indicate an active-low reset |
is input to the micro controller rather than an active-high reset. |
|