|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
#技术风云榜#OR的汇编
9 }- O8 Z( B5 a9 `+ W' C" ^: m本小节,我们将通过一个简单的实验,对OR的汇编(指令集)做一个简单的梳理和测试。
% r' E. u- w9 @- a) C1 t
7 O2 O5 h. z' t$ e C5 H: D1 V. X1,基本思想4 r8 p2 |/ I5 |* n
要想了解OR的指令集,其实只要查查OpenRISC architecture manual就可以了,但是不是最好的熟悉方式,也没有必要将其所有指令集记下来。我认为,通过一个实际的工程或者例子,从中了解OR的指令集是比较好的一种方式。3 s: M7 \+ O( ^1 t3 x
- x0 g# j! J* u: K/ n: p8 |, u
那么,通过什么例子呢?
2 S7 f% s4 L- ]# y
( V4 ~6 p+ @4 }6 V1 J一般RISC的指令集包括,运算指令,分支指令,和访存指令,三类。所以我们这个实验最好能用到这三类指令,碰巧,我最近在测试DDR控制器,所以我们下面将通过一个读写内存的例子来熟悉OR的指令集。) p6 h6 M1 E6 y3 p; \# }* U
' o! ^2 Y$ @7 E8 S5 C
2,实验步骤* u# a; k+ R( w3 V% m& e
2.1实验准备5 v8 V6 q% k2 l7 V I. d" k
在开始编码之前,我们首先需要考虑如下几个问题:9 X* ^& ~# ]% T& R s
0 C" i2 I! b5 ?. M& B' ?9 O5 X+ Z
a,如何对汇编源程序(.S文件)进行编译,生成机器码。* f9 R4 t/ i7 _$ h0 y+ A, ~
+ E3 x) n) O# n' K( Vb,如何加载机器码使OR的指令总线能读到。8 K6 v* p, A8 |, Z
7 \) Y9 ]1 I* G- a
c,如何查看机器码的执行过程和结果。0 w7 Q1 q! _9 l3 p/ _
7 O! M: @( }4 @; s9 g
$ {- _5 m% `0 x \9 `4 v2 A; d5 ?; Y0 ~- k% q
根据前面,我们积累下来的经验,可知,利用bootrom进行RTL仿真,可以很好的解决上面三个问题。并且都是自动化的。
# A$ R% C* V/ I0 M# U0 f
' l9 ]7 v7 W/ G0 @) N
% t, ?$ Z# H7 _6 Y2 ?. r. U, f5 F. J3 P% |3 U
* m) j+ X% a$ b
2 w4 b* q4 U! S
2.2 实验步骤" P( t. s3 T% c) n4 h3 Q
在了解并解决了上面几个问题之后,剩下的就是具体的操作了。' _0 y1 X: {4 G t" [, ~
$ g9 A6 T! G+ y; ]
a,修改soc-design/orpsocv2/sw/bootrom目录下的board.h$ v9 T; ?; J- U! ]3 m8 y9 X2 E5 Z, F
, r' G. C: i2 l: ]* f2 x
8 @& [. m, l. P6 P( w
! c- I1 Y2 c2 ?* O#ifndef _BOARD_H_
7 d; c# P- V; e+ `4 ?#define _BOARD_H_
, U" Z9 m* k9 h: y1 W* t" S& {/ b! i: y) F
//#define IN_CLK 50000000 // Hz1 @, `/ O5 L+ d+ D f5 F
#define IN_CLK 66666667 // Hz9 q" d" t+ _3 ?: V |3 Z
#define PRELOAD_RAM
" U! Z$ t7 Q& J% ~# d#define BOOTROM_MEM_TEST . U+ k3 j& J6 F; E; a% D* {6 I
//
$ k# f3 C* K. d% ?" {# D2 Q// ROM bootloader
# L0 ^7 u! ?8 f. V- ~//* l# E+ O$ M, w' W; w
// Uncomment the appropriate bootloader define. This will effect the bootrom.S2 ]& G# b8 g! B. ~# @! a# ]
// file, which is compiled and converted into Verilog for inclusion at $ t0 b+ K1 a5 N) J. N. u/ V
// synthesis time. See bootloader/bootloader.S for details on each option.% g3 F' [$ E: i, L: z! a
#ifndef PRELOAD_RAM H$ g, j3 D. m& p
#define BOOTROM_SPI_FLASH
1 a3 V- c" @) ~1 v& r//#define BOOTROM_GOTO_RESET
. o; O. U# v2 o//#define BOOTROM_LOOP_AT_ZERO
; P8 C/ r4 f/ G//#define BOOTROM_LOOP_IN_ROM! z9 x1 Z% l: K4 d2 z
#else1 O: q1 T" X# T; _1 \% X. {, V
#ifdef BOOTROM_MEM_TEST+ n+ b1 Y$ @% P! D9 P' I8 |
#define BOOTROM_MEM_TEST1
5 Q( o% W. V" d- d( _, o! X$ A, e #else
/ F0 E4 A% N1 N8 O R2 O. R, d1 o2 B6 o #define BOOTROM_GOTO_RESET2 w3 I7 ]0 K3 H2 k. X
#endif m7 H6 U9 f. @( h" c5 j! d
#endif
' f" d6 X& p$ k0 E9 v; E0 C4 r
; g1 m. k! q @% ?' L9 y// Address bootloader should start from in FLASH$ |9 u0 A- x% E8 v6 P! f1 b
// Last 256KB of 2MB flash - offset 0x1c0000 (2MB-256KB)
: w. x* j4 U7 _& @% ~#define BOOTROM_ADDR_BYTE2 0x1c
9 \) F) K4 O! C3 C#define BOOTROM_ADDR_BYTE1 0x008 Q9 x" x# a* Y7 z5 w, w& T
#define BOOTROM_ADDR_BYTE0 0x00. M- f) b- V7 t* N
// Causes SPI bootloader to loop if SPI didn't give correct size of image
3 e& O) j' J0 r- `* P M5 j0 G#define SPI_RETRY_IF_INSANE_SIZEWORD
( \+ n/ a7 i2 C6 d. i0 E/ V- J
5 T2 W0 {# H: {& C//
" E/ z" r* o& O _// Defines for each core (memory map base, OR1200 interrupt line number, etc.)
/ ^( f5 t% t( |3 p# b# L//3 ^( q" c& J6 M: t2 C- j& P/ z
#define SDRAM_BASE 0x0
1 {( U% ~# d0 g& h7 g7 G
6 B* m- x) u2 i5 Q( W$ H#define GPIO_0_BASE 0x91000000
u4 Z% y7 q) H
/ }& o: i" E0 P# X#define UART0_BASE 0x90000000
" X! c; H3 ^( @0 h, D* y#define UART0_IRQ 2" k# Y! e3 }8 e
#define UART0_BAUD_RATE 115200; L# {# a! p& u; c
, A4 J; O, [. }& V& {
) y; U/ Y2 p$ w9 c# P. g1 Q- h5 T#define SPI0_BASE 0xb00000009 t! j. ^2 f. s" @) q
#define SPI0_IRQ 6& C1 u/ I+ T. Q- P
7 I5 @! h$ [& t9 b8 p1 r
#define I2C_0_BASE 0xa0000000. U9 P+ t3 {7 X* b
#define I2C_0_IRQ 10
& f7 f& J8 O8 ?5 R2 N3 ]9 D7 p* y9 l9 r9 q" m8 |" Y
#define I2C_1_BASE 0xa1000000# T; J. e$ t9 e* F! M2 N: e3 x
#define I2C_1_IRQ 11
9 Y$ `& C) T- M9 Y1 N0 q7 t7 l% [* D1 T8 ~- a+ N/ v: H5 h
#define ETH0_BASE 0x920000000 _9 w1 |. c }, \; h
#define ETH0_IRQ 4# ?5 b& i* k1 l( w/ E+ v
9 s! W9 M8 @0 q
#define ETH_MACADDR0 0x005 e/ V O0 v( G9 z5 w3 v/ I
#define ETH_MACADDR1 0x121 Q }6 O! U2 E* e& n6 ~) |' ^
#define ETH_MACADDR2 0x345 _# G( I4 ` D8 g2 W5 V' t ]
#define ETH_MACADDR3 0x56
; [+ Q2 ?. @5 Z. i; Y( J#define ETH_MACADDR4 0x78; n- h! h% T' g# a* f
#define ETH_MACADDR5 0x9a
: u: o6 q" y! s8 p' h+ M
4 c. [' c/ {* a! K7 W//5 z3 H/ [9 [0 v6 ]7 J; _8 ^
// OR1200 tick timer period define: w# N; W: b/ F$ E
//6 |/ _9 r+ W# l
#define TICKS_PER_SEC 1007 a6 @6 f' f# {* s O9 r
/ l8 n) C2 k% D( y* g. P/ ^7 R
//3 a+ S! W% q% o. B0 i4 N2 T5 j
// CFI flash controller base
9 D( C6 S$ O" @7 v0 l//
H# T5 ?% B$ T2 b1 T#define CFI_CTRL_BASE 0xf00000007 _0 w6 o7 P4 b( l% W% x& ^
+ _) \6 D0 ~2 D! s1 ?# J4 m//: ] p3 }. u4 B) b
// UART driver configuration
7 k8 i3 g2 Q# a0 ?7 I//
1 v; D4 ^: ?+ q0 e4 m; }) q#define UART_NUM_CORES 1
, T" B: W. a- N! j' r#define UART_BASE_ADDRESSES_CSV UART0_BASE3 i' Q5 T: Z9 W" Q: i
#define UART_BAUD_RATES_CSV UART0_BAUD_RATE
% u) N5 H2 w1 D5 r9 h" S j
3 G. n/ E H, K, V* {$ Q, M: Y2 D" C- ]5 ?
//
7 e \/ N/ h& o3 m7 F' ^( K% N% S// i2c_master_slave core driver configuration7 b8 H1 z% b" l! l8 s# o( _1 E. X6 u! O
//, U/ o9 i& J4 `+ q7 Q y) a
# i D1 i" l4 o* Y& a: c#define I2C_MASTER_SLAVE_NUM_CORES 2$ _1 {: E% R3 y& Q# W0 m
. Q! R4 \0 I; Z2 y8 ]$ s
#define I2C_MASTER_SLAVE_BASE_ADDRESSES_CSV \5 S9 U5 b. W4 n4 d
I2C_0_BASE, I2C_1_BASE
/ P: [$ i! g+ m3 g4 l% g7 u7 r+ o7 ?) c! Y( P9 _6 Z
5 o) L6 ~- l ~#endif- [$ K g- Y3 `+ @4 B& l; ^
9 T0 N% M( z& k0 n- ?
8 b, ?& M. n4 p" b" g: T9 {& x7 r/ a- k% [" K
/ Q: e+ y- @2 |8 r; O
4 W6 J) ^! t u8 |' O6 ^5 g# p3 O' `6 N) X* J" P
b,修改soc-design/orpsocv2/sw/bootrom目录下的bootrom.S7 ]) X% N( P# L# M" ~
/ {; U( y3 q' n! }7 ~* ^
这个文件,是需要我们自己手动编写OR的汇编了。
7 j/ ^7 P! t- |) q, P5 {+ Z
1 o$ e/ Q6 t7 j5 `1 \4 J需要注意的有几点。
|; `9 k0 a1 }
# ]$ G9 `9 I1 M, T首先,如何让仿真自动退出:使用“l.nop 1”这条指令,具体原因可参考or1200_monitor.v文件中的相关内容。$ _$ m& Y8 g% {! c P
5 w. E$ v; _" @- f' g" v) e# t其次,如何判断读写内存的成功与失败,分别使用“l.nop 4”和“l.nop 3”。
* b4 O4 \1 l6 ]4 F4 {/ s5 Y# g9 g; L0 N& T$ F: a& i, g
最后,这些汇编,都很容易理解,唯一需要注意的是OR支持延迟槽。( d' [& A3 `1 W6 j
9 U& k" w) j# n' y
下面是具体代码清单:1 ~# D8 M- ~. n* V
; m( f" x2 ?6 W3 p3 q. H# `0 S& J) p6 H- @' g3 u& b# @
: e6 x- l5 K* p//
) D0 d( J/ a0 o7 y& A+ ~///
5 k8 ^+ z9 ^5 `7 B3 n% ^/// bootrom Rill 2014-04-28 ' |6 G$ e- p. M7 C. n% u `
///
' g" x) S# I5 f1 r' ]/ u& B/// Assembly programs to be embedded inside system to aid boot
. a. n, f: h2 V% M9 E/// 9 W& V( ]) P e& J
/// , Z; U4 a5 O& P M/ X3 N
//
' v/ q9 o2 ?# p) z6 ~
% _4 D/ N6 U: E5 _& t& G! W// Defines for which bootrom app to use are in board.h - TODO: use the
: a; C" M, M5 ~! ]// processed orspoc-defines.v file for this define. It makes more sense; o! X* |/ w$ W; E' ^7 B& B7 R
// as this software ends up as gates.
/ A( x- E6 ~' X% _8 P7 H + l7 |& e' ?" d5 X) T
#include "board.h"
9 [" L/ r% b% F u( p" V; w$ `+ G1 S; K9 k" u, t
' l5 A" p+ s7 u+ V' ~9 n/ A0 a. V
#ifdef BOOTROM_MEM_TEST1
! e: ?" ?$ r- g5 J) g) |) B+ n; o: G 7 }0 b! d( j% n6 b/ @
#define RAM_LOAD_BASE 0x1000000 }& X8 J+ k- u# U
#define RESET_ADDR 0x100! i. U" U t% W1 [. O+ L
#define RAM_LOAD_VALUE 0x5555
* @% r: T1 h) D3 B: l#define RAM_LOAD_SIZE 0xc" f! q2 s. b, |
# p' C, V, x: h3 [" h
boot_init:
( a j6 \" I9 _: D. }' C. y l.movhi r0, 0 /*0*/, a. @" k$ H7 P
l.movhi r1, RAM_LOAD_BASE /*1*/
+ I6 N4 l8 o, }0 [% T
. C8 r+ r4 |" c3 Z* \8 R/ rmem_write:
4 _2 o+ R* U0 a, O l.movhi r6, 0 /*2*/ /* counter*/
& f+ C V# C- c9 a# D# D. S3 c l.ori r7, r0, RAM_LOAD_SIZE /*3*/
6 H% J9 G" p6 d. I3 u$ w //l.movhi r7, RAM_LOAD_SIZE; _- H/ A4 R, X8 B
l.movhi r8, 0 /*4*/ /* load addr index*/( }9 q! v. o: R
write:
7 B8 Y+ S) p; y0 F l.ori r3,r0, RAM_LOAD_VALUE /*5*/ /* Read a byte into r3 */
7 U! e: T k% q7 B& r# i l.add r8, r1, r6 /*6*/ /* Calculate store address */( `3 e8 e$ ~5 C
l.sw 0(r8), r3 /*7*/ /* Write byte to memory */
* D. H! t5 I3 e8 H l.addi r6, r6, 4 /*8*/ /* Increment counter */
- d) f0 q' h l4 b ]; U l.sfeq r6, r7 /*9*/ /* Check if we've finished loading the words */0 e+ @4 c+ `3 H, J( j
l.bnf write /*10*/ /* Continue copying if not last word */6 o; O' @( s: \9 U5 C( g( r% h
l.nop /*11*/
- R6 B: }4 b; y. U7 v
1 T2 A3 c0 D3 K; B0 Qmem_read:6 `' ]/ J$ v1 _+ _* G! u* q6 ~
l.movhi r6, 0$ p/ `8 r2 x6 s7 D
l.ori r7, r0, RAM_LOAD_SIZE
, Y7 a _& i( P% _3 }, E! M# ` l.movhi r8, 0' h3 q6 R, B" y, M8 j
read:4 P$ U+ Y' `; \" |7 o. @. I" A
l.add r8, r1, r6
3 \7 G; k. {' ]8 J5 P; s& ~ l.lwz r3, 0(r8)
9 Z4 y# F+ z* b* S l.j check- x9 z$ n: ~4 b- {8 ]
l.nop# j) z# l' d* [+ p+ o9 b
read2:
' u. x: h" ], a# W l.addi r6, r6, 42 C3 r8 ~8 C+ Y( ^1 }# f" ? r5 r
l.sfeq r6, r7
% e4 \) O5 `" Q$ W( k" j l.bnf read9 ^, x' U& `* h O4 m2 s' P
l.nop
: }" p3 q# M' x8 Q6 d l.j success9 S6 ]' t5 v/ B0 v% {
l.nop
$ X3 E9 c/ y$ p/ S8 M" N! _" ?5 r$ O
check:
% j8 C) x+ d( ]0 x2 J l.ori r5,r0, RAM_LOAD_VALUE
: ]$ Z! m: ~" S6 O$ t l.sfeq r3, r5
8 }, v+ i5 ^' x l.bnf error n; D `" A! V. Z
l.nop. e* m3 c* P( S1 P3 u: j6 I1 A
l.j read2, l3 U, ~2 Q- c* D% @. f
l.nop
. }' i" N' M7 F0 }/ e9 n* T" ~+ ?) y+ U7 Y, m( v7 c6 [* ^
error:
+ }' |/ n9 n$ P; G2 R2 k" ? l.nop 3
a, e$ C! X3 |3 R0 y l.j error : z+ J) {! E9 |' A$ I+ i0 T
l.nop 1
( u y- V5 r! q. ]9 X: E# C. E& Q/ c- A! P
success:
4 o* j( A% T! x4 P y$ \4 [ l.nop 4+ Y# A! B, w3 P5 b9 s+ N% ~
l.j success
{, A: p, m9 j) O; y l.nop 1
a" @- O1 T$ d4 [2 Z0 V$ m1 ?# ?/ c. O& Z& s- X. R. a; h4 x
#endif
6 D* f$ l$ b: C; Q6 t7 @3 w* {8 e
X( c# E* q# J; H7 |/ {8 }- E8 y) B* s8 |
" l( [5 e6 O2 ` `9 N o, ?
: `( p7 f5 ?. h. Z/ [- o
% L2 g3 ?+ {9 i9 F7 }2 o# e1 P# f J# h7 F* r% x; c
c,创建C语言裸机测试目录和程序( E- c; y ~: R$ r
5 D6 e' P( I g$ p
由于我们想利用ORPSoC现成的测试环境,所以我们还需要编写一个假的,只是为了满足原有的测试环境的目录和文件。
% g1 r* q4 S- y8 f5 I( `
& z, Y/ |9 p0 X( s3 p/ u# F7 f在soc-design/orpsocv2/board/xilinx/ml501/sw/tests目录下创建目录和文件:5 o- c: `" t9 I& Q5 q
& L, c- p# m* R$ j: [6 t8 c @* c! f# A3 o( A
& H3 ^( z" p' i5 N
mkdir mem
# H8 C4 M N/ |! Ncd mem2 S" i' T) o* r" `, v
touch mem.c7 V, T+ [& q7 y1 d2 V
cp ../../Makefile .) k! b6 v$ |, Q$ ]5 _
1 E: ]3 n7 D6 ]+ [& G. u3 d9 ^& ~4 S( U5 d* o! r( Q% R! S& e
0 j+ r7 ~! A3 O, ]/ }
1 k0 T0 R2 K; ?3 }) S2 A3 h9 M. T
编辑mem.c:
6 I% v6 U6 a% V, L5 J5 m2 @" X F$ r0 L3 z7 H
' r6 `# b+ b, o
; P5 T3 x' d+ U1 ~( {8 y7 E
/*
6 `& r2 u0 O$ O9 a$ ]5 E* Rill
8 G8 \7 V: T! Y& K" |! p' ^4 d$ t8 D* april/28/2014
9 r* ?. M, S# D) M*/7 `9 }: _! {9 ~
# Q# @9 N( M9 C( W( m5 l8 Dint main()
! S) {8 B: t8 t- {* g{' _5 f ^! S: x) m
while(1);//we run instructions in bootrom ONLY.( Q+ B5 ?5 m9 U
return 0;
. X$ @% L) V" B2 f1 n}
. N. p+ W0 d) I& X% u! a1 R, t/ B5 s6 c* f& G
( Z$ F9 [5 A+ S由于我们只运行bootrom.S中的指令,所以mem.c里面写什么语句不重要。
1 m- e! v7 ?) |; B# w1 H* ~7 K# M3 V1 O, q( ]: w
+ Y. R/ _ l$ e6 t' s
6 z, v5 c" ~" ^0 ~d,测试与验证& S. X; u8 |2 a8 @0 O4 \
6 x$ x0 k/ r! e, C" x
完成编码之后,我们就可以运行我们刚才写的汇编程序了,方法我们之前已经介绍过多次了,这里重复如下:# D K: ~0 b' S
2 E3 ]; w/ C+ n6 I在 soc-design/orpsocv2/board/xilinx/ml501/sim/run目录下执行如下:
0 z: H" }% t8 d9 v4 }7 H m
' H+ a9 {' m; ~; p: P- q+ d. v7 h
- O3 f8 l6 c5 d) h, Y o7 j, q4 \( k- K
make rtl-test TEST=mem VCD=1( ]% x, t8 i# y u7 d
7 x: @/ N0 m2 @; o/ t, w d5 U: Y6 v* u7 ]; a4 u/ ~4 Y! E* }: T
很快,我们就可以仿真结束,然后,我们就可以查看仿真日志文件和仿真波形。
4 x; F! X/ R# ]) L( _* w% S5 `0 ]
' X! n( {2 f3 I2 o从中可以看出,对内存的读写都是正确的。+ I1 h% l( P4 }/ p* h( ^: Z, d: K
. r2 @ s# Q* F. Aor1200_monitor输出的日志文件:mem-general.log% S+ v3 C' M9 d1 E
2 t: ~: @- z( Z5 b4 U9 k. J4 E
' `% g% J# ?1 ^7 W0 [
, j. ]: S, D6 e. F; x1 s
58598000.0 ps: l.nop 4 putc (U)
' i3 a! l0 z+ @9 w% O58718000.0 ps: l.nop exit (00005555)1 x; o" u# e& b' C' U" M
+ \" _! v6 D# m I4 F8 [4 [
3 a P$ \3 f: n9 ]5 o% t
+ I2 M. M# J8 w% N" c
8 d% N8 @3 r1 b; c- B ]
6 y) |6 T9 m9 M1 Z" ~
, @3 z F4 e$ pvcd波形文件:
( v8 f' t3 ^% |: h& h, L9 c2 h$ e5 o; ^0 v( M
8 R* P/ y3 j, i; _4 S) I
4 s O$ V% d6 y' O) f! }
) E: S1 v3 N S! A! ?% M2 I# q% Z* S: K) @. _! K
* D) S! M: v n' H8 q5 E
2 y& R4 [) b# L5 V; C$ C
) z3 E9 d1 Y- ]- O5 H4 p
# ?4 d0 \% j& _- [$ x' s3,小结9 ?$ H+ n2 {- E9 b6 p
对于cpu来说,对所有外设(uart,i2c,vga......)的控制都可以通过load/store来完成,和读写内存的实质是完全相同的,所以,通过上面的汇编,我们只要改变一下读写地址修改成对应外设的地址,我们就可以实现对该设备的控制了。
9 M6 L9 g1 T; ]1 P! _# f. L; x# w H% G9 l
当然,编写出优秀的汇编程序也不是一件太容易的事情,这就需要详细阅读OR的架构手册,掌握GPR和SPR的使用方法。甚至,我们还要查看or32-elf-asm来了解更准确的OR的指令集。. H/ z, k2 Y# Z/ ]' m0 g9 K% h
|
|