summaryrefslogtreecommitdiffstats
path: root/zpu/hdl/zealot/devices/trace.vhdl
blob: 83d378257c7ba8287dcd19ed7bb8684b64f68897 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
------------------------------------------------------------------------------
----                                                                      ----
----  ZPU Trace Module                                                    ----
----                                                                      ----
----  http://www.opencores.org/                                           ----
----                                                                      ----
----  Description:                                                        ----
----  ZPU is a 32 bits small stack cpu. This is a module to log an        ----
----  execution trace.                                                    ----
----                                                                      ----
----  To Do:                                                              ----
----  -                                                                   ----
----                                                                      ----
----  Author:                                                             ----
----    - Øyvind Harboe, oyvind.harboe zylin.com                          ----
----    - Salvador E. Tropea, salvador inti.gob.ar                        ----
----                                                                      ----
------------------------------------------------------------------------------
----                                                                      ----
---- Copyright (c) 2008 Øyvind Harboe <oyvind.harboe zylin.com>           ----
---- Copyright (c) 2008 Salvador E. Tropea <salvador inti.gob.ar>         ----
---- Copyright (c) 2008 Instituto Nacional de Tecnología Industrial       ----
----                                                                      ----
---- Distributed under the BSD license                                    ----
----                                                                      ----
------------------------------------------------------------------------------
----                                                                      ----
---- Design unit:      Trace(Behave) (Entity and architecture)            ----
---- File name:        trace.vhdl                                         ----
---- Note:             None                                               ----
---- Limitations:      None known                                         ----
---- Errors:           None known                                         ----
---- Library:          zpu                                                ----
---- Dependencies:     IEEE.std_logic_1164                                ----
----                   IEEE.numeric_std                                   ----
----                   std.textio                                         ----
----                   zpu.zpupkg                                         ----
----                   zpu.txt_util                                       ----
---- Target FPGA:      N/A                                                ----
---- Language:         VHDL                                               ----
---- Wishbone:         No                                                 ----
---- Synthesis tools:  N/A                                                ----
---- Simulation tools: GHDL [Sokcho edition] (0.2x)                       ----
---- Text editor:      SETEdit 0.5.x                                      ----
----                                                                      ----
------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

use std.textio.all;

library zpu;
use zpu.zpupkg.all;
use zpu.txt_util.all;

entity Trace is
   generic(
      LOG_FILE   : string:="trace.txt"; -- Name of the trace file
      ADDR_W     : integer:=16;  -- Address width
      WORD_SIZE  : integer:=32); -- 16/32
   port(
      clk_i      : in std_logic;
      dbg_i      : in zpu_dbgo_t;
      stop_i     : in std_logic;
      busy_i     : in std_logic
      );
end entity Trace;
   
architecture Behave of Trace is
   file l_file : text open write_mode is LOG_FILE;
   signal counter : unsigned(63 downto 0);
begin
   -- write data and control information to a file
   receive_data:
   process
      variable l       : line;
      variable stk_min : unsigned(31 downto 0):=(others => '1');
      variable stk_ini : unsigned(31 downto 0);
      variable first   : boolean:=true;
      variable sp_off  : unsigned(4 downto 0);
      variable idim    : boolean:=false;
      variable im_val  : unsigned(31 downto 0):=(others => '0');
   begin
      counter <= to_unsigned(1,64);
      -- print header for the logfile
      print(l_file,"#PC      Opcode    SP       A=[SP]    B=[SP+1]  Clk Counter        Assembler");
      print(l_file,"#---------------------------------------------------------------------------");
      print(l_file," ");
   
      wait until clk_i='1';
      wait until clk_i='0';
   
      while true loop
         counter <= counter+1;
         if dbg_i.b_inst='1' then
            write(l, "0x"&hstr(dbg_i.pc(ADDR_W-1 downto 0))&
                    " 0x"&hstr(dbg_i.opcode)&
                    " 0x"&hstr(dbg_i.sp)&
                    " 0x"&hstr(dbg_i.stk_a)&
                    " 0x"&hstr(dbg_i.stk_b)&
                    " 0x"&hstr(counter)&" ");
            --------------------------
            -- Instruction Decoder  --
            --------------------------
            sp_off(4):=not dbg_i.opcode(4);
            sp_off(3 downto 0):=dbg_i.opcode(3 downto 0);
            if dbg_i.opcode(7 downto 7)=OPCODE_IM then
               if idim then
                  im_val(31 downto 7):=im_val(24 downto 0);
                  im_val(6 downto 0):=dbg_i.opcode(6 downto 0);
               else
                  im_val:=unsigned(resize(signed(dbg_i.opcode(6 downto 0)),32));
               end if;
               idim:=true;
               write(l,"im 0x"&hstr(dbg_i.opcode(6 downto 0))&" ; 0x"&hstr(im_val));
            elsif dbg_i.opcode(7 downto 5)=OPCODE_STORESP then
               if sp_off=0 then
                  write(l,string'("storesp 0 ; pop"));
               elsif sp_off=1 then
                  write(l,string'("storesp 4 ; 1*4 = popdown"));
               else
                  write(l,"storesp "&integer'image(to_integer(sp_off)*4)&" ; "&
                        integer'image(to_integer(sp_off))&"*4");
               end if;
            elsif dbg_i.opcode(7 downto 5)=OPCODE_LOADSP then
               if sp_off=0 then
                  write(l,string'("loadsp 0 ; dup"));
               elsif sp_off=1 then
                  write(l,string'("loadsp 4 ; 1*4 = dupstkb"));
               else
                  write(l,"loadsp "&integer'image(to_integer(sp_off)*4)&" ; "&
                        integer'image(to_integer(sp_off))&"*4");
               end if;
            elsif dbg_i.opcode(7 downto 5)=OPCODE_EMULATE then
               if dbg_i.opcode(5 downto 0)=OPCODE_EQ then
                  write(l,string'("eq"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_LOADB then
                  write(l,string'("loadb"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_NEQBRANCH then
                  write(l,string'("neqbranch"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_PUSHSPADD then
                  write(l,string'("pushspadd"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_LESSTHAN then
                  write(l,string'("lessthan"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_ULESSTHAN then
                  write(l,string'("ulessthan"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_MULT then
                  write(l,string'("mult"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_STOREB then
                  write(l,string'("storeb"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_CALLPCREL then
                  write(l,string'("callpcrel"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_SUB then
                  write(l,string'("sub"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_LESSTHANOREQUAL then
                  write(l,string'("lessthanorequal"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_ULESSTHANOREQUAL then
                  write(l,string'("ulessthanorequal"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_CALL then
                  write(l,string'("call"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_POPPCREL then
                  write(l,string'("poppcrel"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_LSHIFTRIGHT then
                  write(l,string'("lshiftright"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_LOADH then
                  write(l,string'("loadh"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_STOREH then
                  write(l,string'("storeh"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_ASHIFTLEFT then
                  write(l,string'("ashiftleft"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_ASHIFTRIGHT then
                  write(l,string'("ashiftright"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_NEQ then
                  write(l,string'("neq"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_NEG then
                  write(l,string'("neg"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_XOR then
                  write(l,string'("xor"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_DIV then
                  write(l,string'("div"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_MOD then
                  write(l,string'("mod"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_EQBRANCH then
                  write(l,string'("eqbranch"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_CONFIG then
                  write(l,string'("config"));
               elsif dbg_i.opcode(5 downto 0)=OPCODE_PUSHPC then
                  write(l,string'("pushpc"));
               else
                  write(l,integer'image(to_integer(dbg_i.opcode(5 downto 0)))&
                        " ; invalid emulated instruction");
               end if;
            elsif dbg_i.opcode(7 downto 4)=OPCODE_ADDSP then
               if sp_off=0 then
                  write(l,string'("addsp 0 ; shift"));
               elsif sp_off=1 then
                  write(l,string'("addsp 4 ; 1*4 = addtop"));
               else
                  write(l,"addsp "&integer'image(to_integer(sp_off)*4)&" ; "&
                        integer'image(to_integer(sp_off))&"*4");
               end if;
            else -- OPCODE_SHORT
               case dbg_i.opcode(3 downto 0) is
                    when OPCODE_BREAK =>
                         write(l,string'("break"));
                    when OPCODE_PUSHSP =>
                         write(l,string'("pushsp"));
                    when OPCODE_POPPC =>
                         write(l,string'("poppc"));
                    when OPCODE_ADD =>
                         write(l,string'("add"));
                    when OPCODE_OR =>
                         write(l,string'("or"));
                    when OPCODE_AND =>
                         write(l,string'("and"));
                    when OPCODE_LOAD =>
                         write(l,string'("load"));
                    when OPCODE_NOT =>
                         write(l,string'("not"));
                    when OPCODE_FLIP =>
                         write(l,string'("flip"));
                    when OPCODE_STORE =>
                         write(l,string'("store"));
                    when OPCODE_POPSP =>
                         write(l,string'("popsp"));
                    when OPCODE_NOP =>
                         write(l,string'("nop"));
                    when others =>
                         write(l,integer'image(to_integer(dbg_i.opcode))&
                               " ; invalid instruction");
               end case;
            end if;
            if dbg_i.opcode(7 downto 7)/=OPCODE_IM then
               idim:=false;
            end if;
            -----------------------------
            -- End Instruction Decoder --
            -----------------------------
            writeline(l_file,l);
            if dbg_i.sp<stk_min then
               stk_min:=dbg_i.sp;
            end if;
            if first then
               stk_ini:=dbg_i.sp+8;
               first:=false;
            end if;
         end if;
         wait until clk_i='0' or stop_i='1';
         if stop_i='1' then
            print(output,"Minimum SP: 0x"&hstr(stk_min)&" Size: 0x"&hstr(stk_ini-stk_min));
            wait;
         end if;
      end loop;
   end process receive_data;
end Behave;
 
OpenPOWER on IntegriCloud