|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
#技术风云榜#OR的汇编# ]' c( t& c3 I! d: ?& A2 x
本小节,我们将通过一个简单的实验,对OR的汇编(指令集)做一个简单的梳理和测试。& v# S8 v5 X$ k. M4 P
8 z& V. d5 b( n6 ]0 {7 E2 m
1,基本思想
: _1 W. E1 S) q要想了解OR的指令集,其实只要查查OpenRISC architecture manual就可以了,但是不是最好的熟悉方式,也没有必要将其所有指令集记下来。我认为,通过一个实际的工程或者例子,从中了解OR的指令集是比较好的一种方式。+ {4 x: Q% l$ V7 d6 ~$ u/ J' Z
$ N* ~7 n* z- U+ P+ [( T那么,通过什么例子呢?7 x1 G" B0 T. S
0 M% _: `0 W2 i: O1 h
一般RISC的指令集包括,运算指令,分支指令,和访存指令,三类。所以我们这个实验最好能用到这三类指令,碰巧,我最近在测试DDR控制器,所以我们下面将通过一个读写内存的例子来熟悉OR的指令集。8 Y i1 Q- g# \% ? R% {, x* ^
8 o E" f( Y& \5 @/ v% C
2,实验步骤
# E; ]; B. J, A. w2.1实验准备
1 \7 T; P X; ]! x+ a9 D在开始编码之前,我们首先需要考虑如下几个问题:+ @8 C5 [& }9 d
8 ~9 j8 W; U5 t4 A1 z: ~! N1 j# t U1 O
a,如何对汇编源程序(.S文件)进行编译,生成机器码。( y, m& O( X9 I0 N1 J; Z, D
$ S: P8 {: q. j0 X* nb,如何加载机器码使OR的指令总线能读到。- R5 Q) g- q# R. N, X t
. ?! A; g) R1 n" Ac,如何查看机器码的执行过程和结果。
. e \/ }: l' ]' J- L0 F
! M4 \7 E3 U3 O9 w! O; {. o8 T1 H
7 [ Q4 s' G; @: y$ G* Q
根据前面,我们积累下来的经验,可知,利用bootrom进行RTL仿真,可以很好的解决上面三个问题。并且都是自动化的。
4 c! m T. [, C# n* z- h" F4 x: D& u8 @5 |( R
) M# X. e$ R" W9 {3 u# o
6 Z. d; ^* X! H: q2 U+ c- v$ X3 B/ i& D$ n3 ?
# ?% F8 B0 k" K- R* Z
2.2 实验步骤
7 n! D( Y3 z6 x在了解并解决了上面几个问题之后,剩下的就是具体的操作了。. |! o7 f$ S4 G J1 ]
3 S0 E: |2 Z- b& r5 i8 @6 xa,修改soc-design/orpsocv2/sw/bootrom目录下的board.h+ s& P( y4 }- W& h) Q
: f& C5 |1 c7 E, O/ z' P
9 A1 ?: N8 @: q U" Y
; {. ^$ i6 f& w1 F0 H6 r#ifndef _BOARD_H_7 o" T* N- x" {7 ?1 \: ]) }
#define _BOARD_H_" [1 d# c4 P0 w" ~; o7 Q
% r5 |( Y2 e2 k. W {- S! h
//#define IN_CLK 50000000 // Hz
2 r/ |' ^. _$ {3 J#define IN_CLK 66666667 // Hz
' t5 b+ U6 e- |$ B4 Q0 e#define PRELOAD_RAM
; q! G) _, v5 I% c3 y#define BOOTROM_MEM_TEST ; T4 S) E/ ?! }
// w8 w$ Z! N& w
// ROM bootloader/ V: z- v O N# ~# F" M
//& U! L$ j6 R& l% A
// Uncomment the appropriate bootloader define. This will effect the bootrom.S+ b7 t4 J4 ^7 K+ j- Q
// file, which is compiled and converted into Verilog for inclusion at ! G u0 D4 Q3 O( e) E5 d( Y! K8 @
// synthesis time. See bootloader/bootloader.S for details on each option.' C; Y! H9 Y" E& o4 I* R
#ifndef PRELOAD_RAM
5 W& d7 V# s8 H2 G#define BOOTROM_SPI_FLASH. `0 n u0 N! i8 a* h
//#define BOOTROM_GOTO_RESET5 G- ~( Q3 n1 f2 Z; F0 S4 R
//#define BOOTROM_LOOP_AT_ZERO. r: l$ ~( O8 t; [' k
//#define BOOTROM_LOOP_IN_ROM
5 O! @# o, m9 P+ Q; n6 W#else/ }9 ~9 Y. k0 c U
#ifdef BOOTROM_MEM_TEST4 G% M2 K- J" Q' B: A& a- E
#define BOOTROM_MEM_TEST1
- f+ O5 I( B+ f, m #else: s1 x& L, p1 m5 L, I) ?
#define BOOTROM_GOTO_RESET
" Q9 ]- |# ? J. e9 @ #endif
) O5 q+ d# ?0 ~#endif
2 f) k. ~( B. `( s6 e; ?- ?5 N8 T! A( z4 |
// Address bootloader should start from in FLASH% k: c& s) j" J y
// Last 256KB of 2MB flash - offset 0x1c0000 (2MB-256KB)
3 U7 _1 i! S K# R0 W- d+ M% B5 S#define BOOTROM_ADDR_BYTE2 0x1c+ Z! @/ s$ Q8 g$ U, l
#define BOOTROM_ADDR_BYTE1 0x00
. Z( m$ j$ n4 N5 n; W$ ]+ K* |6 O#define BOOTROM_ADDR_BYTE0 0x00
* ^, Z, \9 W) H7 W3 ~. j// Causes SPI bootloader to loop if SPI didn't give correct size of image
/ C& v1 [+ M0 f- N2 _/ I' c#define SPI_RETRY_IF_INSANE_SIZEWORD
/ M4 D4 k( L6 o- I# L, D0 ] O
/ ~8 z1 `: }* @( v//% f9 K5 j9 V9 r: i7 v- f4 z
// Defines for each core (memory map base, OR1200 interrupt line number, etc.)
* d9 K# b( x" a/ R//; O9 Q+ E: c' c# X, v
#define SDRAM_BASE 0x0$ b0 r3 n z* C S" G
0 V* i8 N$ o' N
#define GPIO_0_BASE 0x91000000& D7 c9 y s0 }1 d
1 @3 q& g0 ~& u$ z# h& p6 I$ [ T
#define UART0_BASE 0x900000002 n( P" Y2 S# @( ~1 O4 _# z
#define UART0_IRQ 26 }' u5 W2 ^/ k5 A6 U4 k2 d
#define UART0_BAUD_RATE 115200+ |- [, s+ T+ Y' c) R7 [
. z% [/ L' o% D& ^) Q
8 V& |) q+ @) |#define SPI0_BASE 0xb0000000% W8 g Q4 c& u# o7 }
#define SPI0_IRQ 6% \$ l' t3 p4 F5 `5 N, \+ w
7 {' ?3 \# `0 E
#define I2C_0_BASE 0xa0000000
7 E+ \& m0 b+ [! z% u#define I2C_0_IRQ 101 N* Y% {. ?- p+ v$ ]
" E3 x# C# m. v; [
#define I2C_1_BASE 0xa1000000
0 ?) |) Y/ } o, i/ h) L#define I2C_1_IRQ 11
* W% z' r# b ^: x. A8 @! O, m& R3 A) S# [& z/ e
#define ETH0_BASE 0x92000000
% H, n7 u- l) @6 S#define ETH0_IRQ 4
' u$ q- v4 i4 x u4 K$ V( g4 @' f5 M4 E1 i
#define ETH_MACADDR0 0x00
, U6 [/ C0 a% ~% C. b+ w% K# c2 i#define ETH_MACADDR1 0x12
' B) ]' P: o% D3 \0 o$ D% x$ a#define ETH_MACADDR2 0x34
/ D4 w" I& e7 \2 V y#define ETH_MACADDR3 0x56
. y; S9 N5 g0 c0 x7 ?#define ETH_MACADDR4 0x788 O' @; c. v3 a1 J( c1 o p2 I
#define ETH_MACADDR5 0x9a' x, d, F% p( R+ q/ ?1 D3 j
8 d) i6 F; p/ l2 X K# d6 {
//( S! Q8 A+ j8 Z. M; [& l8 I! i
// OR1200 tick timer period define. |8 ?4 x4 H# f" H1 Y
//: G1 K9 a# d7 d+ {( x
#define TICKS_PER_SEC 100
% f6 k) e, }7 M& t) ^6 `% r
9 Z4 Z# h7 E& W4 U0 L' J//' j! K2 }) r* ]1 Y
// CFI flash controller base
: T! C" I9 f0 t: M9 o//; X5 Q6 p2 o) D* h
#define CFI_CTRL_BASE 0xf00000002 H0 W; b" I/ ^" b0 A1 R
9 ?# M [4 J/ u# `# O//
0 B: s; r' r& j: M6 V O4 L6 h3 N5 n* |// UART driver configuration
$ u8 m+ P- O" n+ W( H% K// ! j, b4 }6 x9 j. P2 o7 \+ n
#define UART_NUM_CORES 1
0 c( q' B3 D0 D+ x6 Q& }3 h#define UART_BASE_ADDRESSES_CSV UART0_BASE
: V/ @: F! ^' n& f* v#define UART_BAUD_RATES_CSV UART0_BAUD_RATE
I$ J; K9 l5 H1 `2 W0 _ p
& n! s) `8 @% @( R& ]8 Y d9 N0 I6 f1 ~3 W+ Q1 ]) Q' D4 R
//
# g- |$ R9 K7 h3 n5 y1 K6 S2 D// i2c_master_slave core driver configuration
! P! f: K2 `& y/ Q: D//& z8 Z5 ~( H6 |% e: j& r
$ [1 @6 V2 a" ~ ?- }
#define I2C_MASTER_SLAVE_NUM_CORES 22 c; ^) R: [1 @' A
: _( b* U' ^ d2 Y
#define I2C_MASTER_SLAVE_BASE_ADDRESSES_CSV \2 F& o( F$ q2 p+ R( O1 A- ]4 F# ]
I2C_0_BASE, I2C_1_BASE% k# H2 q. u9 p
+ ~1 I8 d- b; f5 n6 U; Q3 d0 u( ]- ^! B E. A- k
#endif- @$ ~. p. n7 l: f6 c$ A. a
+ v% i. d ?) w. L* F! B6 D7 @2 H9 b% `' l5 }. f' P
3 G5 d, O9 q4 l" @8 G, ?% i; o% U1 s8 }) d- G/ b% f* }
1 y. V. V/ N z' I4 M) D
1 E4 R0 R1 y2 @5 K
b,修改soc-design/orpsocv2/sw/bootrom目录下的bootrom.S, w3 G; X) h4 n8 a
' k% m `/ M. D3 K& S) U: a这个文件,是需要我们自己手动编写OR的汇编了。! o; Q5 O& r) `5 n4 P" c
% Y H# n& H# N) z+ q
需要注意的有几点。
$ G; u3 k; V8 `9 s. O/ o8 q
7 P( S! k+ S2 T/ T( u首先,如何让仿真自动退出:使用“l.nop 1”这条指令,具体原因可参考or1200_monitor.v文件中的相关内容。- J1 H: u# _, J
/ q* A; ] w9 I1 J其次,如何判断读写内存的成功与失败,分别使用“l.nop 4”和“l.nop 3”。
! Z9 n4 K% c" G% p8 p6 u4 ], U0 Y( i9 d N2 U
最后,这些汇编,都很容易理解,唯一需要注意的是OR支持延迟槽。$ O8 D0 H, b! F5 k( s
; x6 W7 j( d0 W下面是具体代码清单:0 f+ G" e, m7 b7 v: `6 S+ |
- u( T8 v" A5 L5 n. A4 S( J% R2 V: @, a
1 l( J0 l; s4 P2 W+ m
5 B0 v4 S8 \+ h1 v* U//! _ C6 c1 _2 u& t' e% i
/// 8 V" o5 z N( N8 p
/// bootrom Rill 2014-04-28
; J' `8 C, U2 H- ], S/// . Y; z* ~+ s, l" [0 T5 g/ P
/// Assembly programs to be embedded inside system to aid boot 2 g$ \' }/ N+ _( M* T$ } }
/// + j& u ~/ U/ _. [$ o. Z/ R
///
& N1 a$ R7 ]. G: x$ C2 H//0 Q: k8 u* n; n1 e! q
4 [7 \5 I4 j( _- x# S8 o1 E// Defines for which bootrom app to use are in board.h - TODO: use the
0 G" T: G* u% f/ }/ p! F5 @5 a, G// processed orspoc-defines.v file for this define. It makes more sense
) h# \+ C2 M+ G' t; D1 \// as this software ends up as gates.3 f6 K1 y, J# ^
" Z B4 X n4 j1 C m7 M: v#include "board.h") m7 I% Y( i+ T' A ?0 W N9 M
i9 }2 t% \! D+ m6 a4 K- G# R
; o; V9 v4 z$ U#ifdef BOOTROM_MEM_TEST1" e) p1 L& V8 e' l# C
5 g) a% l/ x. Q; n#define RAM_LOAD_BASE 0x1000004 Z" D' @$ I9 X: t! i8 y4 w" o
#define RESET_ADDR 0x100
: w; Z" h6 B$ ]% l#define RAM_LOAD_VALUE 0x5555
% F* \9 Z1 C4 x5 U0 m! p1 ?% D I* W#define RAM_LOAD_SIZE 0xc
1 C' i, B9 S2 n n
( r! \5 a9 u, j9 w+ \boot_init:
; a/ l2 i/ L+ Z# ]; {, i l.movhi r0, 0 /*0*/; ^. d* }6 p+ f9 r1 O# x* c8 \
l.movhi r1, RAM_LOAD_BASE /*1*/
! j8 ^6 ~9 K8 d% r) |
9 Z# O) _4 G. C" a fmem_write:! U# {! w% L0 _) n7 {9 m# w
l.movhi r6, 0 /*2*/ /* counter*/
1 g9 i2 ~! ?3 \% Q1 J: ` l.ori r7, r0, RAM_LOAD_SIZE /*3*/
% X! M" I( S- ^8 P0 a; w! Q1 K //l.movhi r7, RAM_LOAD_SIZE
5 E: Z, J) M5 \, Q) G3 J l.movhi r8, 0 /*4*/ /* load addr index*/' j, P! \. s8 j$ \( Q: {
write:
% ]( |" X* f* r/ y: r" l l.ori r3,r0, RAM_LOAD_VALUE /*5*/ /* Read a byte into r3 */: n9 L2 S" i, u" I: e, _
l.add r8, r1, r6 /*6*/ /* Calculate store address */
- J! r. P* |" U k7 b# E) w- H l.sw 0(r8), r3 /*7*/ /* Write byte to memory */& Y* D' _( B3 X7 t
l.addi r6, r6, 4 /*8*/ /* Increment counter */
8 P8 ?6 `1 g" S: _) O l.sfeq r6, r7 /*9*/ /* Check if we've finished loading the words */$ u# V$ x, E# l
l.bnf write /*10*/ /* Continue copying if not last word */
; S6 I, p3 B) [ l.nop /*11*// q9 \7 m, u& }2 n% ?. J; s
2 Y7 i! Q! ?. b. Lmem_read:
6 t$ n- p3 K4 `% U& f; t$ G5 C l.movhi r6, 0
$ K ^1 p2 R# N% o l.ori r7, r0, RAM_LOAD_SIZE
" w2 ?) x, M1 m: a! @; k9 M l.movhi r8, 0! n7 I2 [) ]8 C7 R
read:4 p% ?" ^+ K+ U+ A1 t
l.add r8, r1, r6: c4 a( Q3 q6 h( D" D. [
l.lwz r3, 0(r8)
- ]. i1 s$ E6 t/ @; f" h# U+ a l.j check
: F. c$ a1 W* w l.nop3 g0 ^' c( n* B8 B& e- _7 M0 r
read2:4 Z5 r& ?3 p8 y9 t! z1 O
l.addi r6, r6, 42 c. p" X6 N0 C/ y
l.sfeq r6, r73 v& O5 {: `) ]/ W
l.bnf read1 _, V: L+ P) P- k' G3 F
l.nop: S* T+ a4 }( M9 }! h
l.j success+ @. X0 c2 B6 J1 v& i; k; e
l.nop3 y2 |1 n: h1 I; Q- D
" {( }6 B0 t9 Q6 Icheck:; O' S$ d& x s( g( b; ~3 n1 {- t
l.ori r5,r0, RAM_LOAD_VALUE
3 I: U, O2 \; H7 Q l.sfeq r3, r5. I( p$ b B( V. x/ D# d
l.bnf error
: F H. e& _1 h. T* v* o l.nop0 t: }( U& S; v$ N0 [- m8 P% ^
l.j read25 ?! A- ?9 Q( {8 s% u" a9 ]7 k; |; L& L1 @
l.nop
1 c( M! A* Q3 D3 c$ S- u3 A# c5 g) r9 w' h, c" B$ @/ j1 Y
error:
. P! [ j; X! ^5 @) M5 s7 X; I l.nop 3
4 C. m6 n7 p. | l.j error
" l# Y% n- ^1 c- S1 K, r l.nop 10 D! X( n8 ]& N
# |" m& l x) \4 tsuccess:8 ]! H: W- h1 h
l.nop 40 ?& w! v4 W* W' x% {, e
l.j success
$ ?: P& D. |* I2 Y8 d/ s' y l.nop 1% ^' I1 C. M7 g* o3 ~7 C* o. r
* G, o( t" B& {( G, C. A#endif
J* G) c3 e8 X/ F* P) U* v% N
1 c* s8 c" ?3 ~- f
# {! V' ^2 }4 d1 t1 L- |
7 K# G& L9 U# D# ~8 v! t! D& x4 x& r2 I5 A
! h- j. c' f$ o0 X! N, B9 g
i- n1 _% M* g( e8 j
c,创建C语言裸机测试目录和程序' f& k7 z- E0 @" S9 d2 z" o. B' I0 d
% W# @7 ^8 |8 d* J2 @
由于我们想利用ORPSoC现成的测试环境,所以我们还需要编写一个假的,只是为了满足原有的测试环境的目录和文件。+ d8 \' p& \5 ]+ I0 O
" P8 o% R9 H: d* ~4 P4 `
在soc-design/orpsocv2/board/xilinx/ml501/sw/tests目录下创建目录和文件:
% B! U* T9 a8 z8 R* _, @" @) Z6 o3 ~$ Z0 i; d: c
" a2 {; b+ Z7 g: n/ T0 c( b* E
) P. m( ^* a5 ~3 M7 f3 y/ Y+ c
mkdir mem
) d; N8 {, k6 fcd mem+ G T+ x' v( q5 ]- @+ ]7 P, X
touch mem.c R0 Q4 y' q4 [3 w$ H) a7 U' V
cp ../../Makefile .0 _# H. @5 P; c
6 S# O1 K, m' k9 Y4 A; T4 f/ C
/ P3 Z& [- ^' b- [) v' M9 F; ~ |; n7 `- d8 C$ k
7 X: [$ \" J3 M5 s编辑mem.c:
. S1 W# h- b( y- Y5 K8 c* f% v- h, F4 k+ M
; `; {- M9 o$ O. e4 U
, w& m& _- V3 ?. w c/*
+ ]' ^) R7 A% j$ E* e2 o* I. Y* Rill& T0 J8 B* l5 m0 ~7 L) ^5 L
* april/28/2014! w1 k, y7 M5 h* i0 B& U! x" E, |
*/; r) Y% R4 ~1 g- d* U. q! `2 f
5 z2 x, u& F# L. [6 V( h5 oint main()
' ]9 ~% _! \8 N$ \" J0 S6 d{3 w' q. p0 C( J; C; |1 ^
while(1);//we run instructions in bootrom ONLY.+ d8 [$ b* l' A9 D# r+ Q
return 0;
M7 A1 }* v. o$ ^! I6 e% d}/ n' Z0 V7 k8 o; b, O
0 u: D- |' h9 @% k @
' U8 u) x3 G% t9 W由于我们只运行bootrom.S中的指令,所以mem.c里面写什么语句不重要。
( [1 ?! o" P8 U8 |1 Z9 E, g& W5 U$ @) a
1 D+ C2 K& M$ O' B8 h' ~) m# T. o
" n* S, W$ w$ z6 ?$ Zd,测试与验证' D$ O5 m& R1 W- O Q
( [- r; }; l% @完成编码之后,我们就可以运行我们刚才写的汇编程序了,方法我们之前已经介绍过多次了,这里重复如下:/ t/ g. n7 `4 Y/ y: l# O5 `' C; P
3 c. A( p: Z4 }2 h
在 soc-design/orpsocv2/board/xilinx/ml501/sim/run目录下执行如下:
- x K2 O% |, W t/ t# r% J
6 N; W: ]- T+ O. t5 `! A7 {
0 C, I5 y( \8 p) I: A6 M( e
/ I! x+ ?" i: J. P8 M8 Emake rtl-test TEST=mem VCD=11 o2 Z7 X* y* ?, z" m4 V/ Y" H& G
9 ^/ p$ A6 Z4 b9 ] d
8 [1 i8 }; ~! \/ a) v- @6 G" l很快,我们就可以仿真结束,然后,我们就可以查看仿真日志文件和仿真波形。) X' H/ k1 I C
0 \: B# O1 O: M
从中可以看出,对内存的读写都是正确的。
- b3 E7 `3 ^6 \( f5 C
( \3 K7 U/ b4 F8 nor1200_monitor输出的日志文件:mem-general.log
9 |# ?/ y( ^; k) R$ X0 e# m' r7 Q- Z$ `0 G: w% q' g7 L0 `8 {
+ {, W" l$ ? x* \- I3 s# @. l0 `; N' `( \( m0 p4 M+ \2 s0 ~
58598000.0 ps: l.nop 4 putc (U), N9 A+ p8 B% V
58718000.0 ps: l.nop exit (00005555)
- l, G+ ?" I, G! |! c( @+ E6 G* ~: z" A' }$ h& Y. C/ u/ {
$ F5 l2 x9 X; }2 H) A6 C
$ K1 I$ G2 D- U/ g* a
! _( W3 g; `* s& \) ~/ Q( Z4 K9 t0 X
. P5 x! P3 x( C# `# }8 }vcd波形文件:% T( d0 b7 W5 j9 l& c7 J
2 w& s/ ^. ~+ g
, i1 a/ Q* f7 ~8 d* ]# A6 X; W5 \7 L4 u
* H* u: X* b {$ @* E* F& `
: k% b1 H4 _3 F" M9 M3 S
1 K+ I% q( C6 \
; b& i1 ~; U4 N! V! g9 U8 P
: b9 n; q n# r f5 l
0 W8 x& m3 A/ v, B8 Z" T; h s0 s3,小结- ]- i$ W; L9 S& n V Y8 n' y$ I
对于cpu来说,对所有外设(uart,i2c,vga......)的控制都可以通过load/store来完成,和读写内存的实质是完全相同的,所以,通过上面的汇编,我们只要改变一下读写地址修改成对应外设的地址,我们就可以实现对该设备的控制了。* q7 D+ U/ D7 P+ p
- u/ a: b. H! D! D' ]
当然,编写出优秀的汇编程序也不是一件太容易的事情,这就需要详细阅读OR的架构手册,掌握GPR和SPR的使用方法。甚至,我们还要查看or32-elf-asm来了解更准确的OR的指令集。
; V9 x9 D. y* X( l! ] |
|