Project

General

Profile

Download (16.8 KB) Statistics
| Branch: | Tag: | Revision:
1

    
2
-- Copyright (C) 1996 Morgan Kaufmann Publishers, Inc
3

    
4
-- This file is part of VESTs (Vhdl tESTs).
5

    
6
-- VESTs is free software; you can redistribute it and/or modify it
7
-- under the terms of the GNU General Public License as published by the
8
-- Free Software Foundation; either version 2 of the License, or (at
9
-- your option) any later version. 
10

    
11
-- VESTs is distributed in the hope that it will be useful, but WITHOUT
12
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
-- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
-- for more details. 
15

    
16
-- You should have received a copy of the GNU General Public License
17
-- along with VESTs; if not, write to the Free Software Foundation,
18
-- Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
19

    
20
-- ---------------------------------------------------------------------
21
--
22
-- $Id: ch_15_dlx-b.vhd,v 1.4 2001-11-03 23:19:37 paw Exp $
23
-- $Revision: 1.4 $
24
--
25
-- ---------------------------------------------------------------------
26

    
27
library bv_utilities;
28
use bv_utilities.bv_arithmetic.all;
29

    
30
library work;
31
use work.dlx_instr.all;
32

    
33
architecture behavior of dlx is
34
begin
35

    
36
  interpreter : process
37
    is
38

    
39
    type reg_array is array (reg_index) of dlx_bv_word;
40
    variable reg : reg_array;
41
    variable fp_reg : reg_array;
42

    
43
    variable PC : dlx_bv_word;
44
    constant PC_incr : dlx_bv_word := X"0000_0004";
45

    
46
    variable IR : dlx_bv_word;
47
    alias IR_opcode : dlx_opcode is IR(0 to 5);
48
    alias IR_sp_func : dlx_sp_func is IR(26 to 31);
49
    alias IR_fp_func : dlx_fp_func is IR(27 to 31);
50
    alias IR_rs1 : dlx_reg_addr is IR(6 to 10);
51
    alias IR_rs2 : dlx_reg_addr is IR(11 to 15);
52
    alias IR_Itype_rd : dlx_reg_addr is IR(11 to 15);
53
    alias IR_Rtype_rd : dlx_reg_addr is IR(16 to 20);
54
    alias IR_immed16 : dlx_immed16 is IR(16 to 31);
55
    alias IR_immed26 : dlx_immed26 is IR(6 to 31);
56

    
57
    variable disassembled_instr : string(1 to 40);
58
    variable disassembled_instr_len : positive;
59

    
60
    variable rs1, rs2, Itype_rd, Rtype_rd : reg_index;
61

    
62
    variable mem_addr_reg : dlx_bv_address;
63
    variable mem_data_reg : dlx_bv_word;
64

    
65
    variable overflow : boolean;
66

    
67
    -- lookup table for result of set instructions
68
    type set_result_table is array (boolean) of dlx_bv_word;
69
    constant set_if : set_result_table := ( false => X"0000_0000",
70
                                            true => X"0000_0001" );
71
    variable instr_count : natural;
72

    
73

    
74
    -- local procedures for use within the interpreter
75

    
76

    
77
    procedure bus_read ( address : in dlx_bv_address;
78
                         data_width : in dlx_mem_width;
79
                         instr_fetch : in std_logic;
80
                         data : out dlx_bv_word ) is
81

    
82
    begin
83
      wait until rising_edge(phi1);
84
      if To_bit(reset) = '1' then
85
        return;
86
      end if;
87
      a <= To_X01(address) after Tpd_clk_out;
88
      width <= data_width after Tpd_clk_out;
89
      ifetch <= instr_fetch after Tpd_clk_out;
90
      mem_enable <= '1' after Tpd_clk_out;
91
      loop 
92
        wait until falling_edge(phi2);
93
        if To_bit(reset) = '1' then
94
          return;
95
        end if;
96
        exit when To_bit(ready) = '1';
97
      end loop;
98
      assert not Is_X(d) report "Bus read data contains unknown bits";
99
      data := To_bitvector(d);
100
      mem_enable <= '0' after Tpd_clk_out;
101
    end procedure bus_read;
102

    
103

    
104
    procedure bus_write ( address : in dlx_bv_address;
105
                          data_width : in dlx_mem_width;
106
                          data : in dlx_bv_word ) is
107

    
108
    begin
109
      wait until rising_edge(phi1);
110
      if To_bit(reset) = '1' then
111
        return;
112
      end if;
113
      a <= To_X01(address) after Tpd_clk_out;
114
      ifetch <= '0' after Tpd_clk_out;
115
      width <= data_width after Tpd_clk_out;
116
      d <= To_X01Z(data) after Tpd_clk_out;
117
      write_enable <= '1' after Tpd_clk_out;
118
      mem_enable <= '1' after Tpd_clk_out;
119
      loop 
120
        wait until falling_edge(phi2);
121
        if To_bit(reset) = '1' then
122
          return;
123
        end if;
124
        exit when To_bit(ready) = '1';
125
      end loop;
126
      d <= disabled_dlx_word after Tpd_clk_out;
127
      write_enable <= '0' after Tpd_clk_out;
128
      mem_enable <= '0' after Tpd_clk_out;
129
    end procedure bus_write;
130

    
131

    
132
    procedure execute_op_special is
133
    begin
134
      case IR_sp_func is
135
        when sp_func_nop =>
136
          null;
137
        when sp_func_add => 
138
          bv_add(reg(rs1), reg(rs2), reg(Rtype_rd), overflow);
139
        when sp_func_addu => 
140
          bv_addu(reg(rs1), reg(rs2), reg(Rtype_rd), overflow);
141
        when sp_func_sub => 
142
          bv_sub(reg(rs1), reg(rs2), reg(Rtype_rd), overflow);
143
        when sp_func_subu => 
144
          bv_subu(reg(rs1), reg(rs2), reg(Rtype_rd), overflow);
145
        when sp_func_sll => 
146
          reg(Rtype_rd) := reg(rs1) sll bv_to_natural(reg(rs2)(27 to 31));
147
        when sp_func_srl => 
148
          reg(Rtype_rd) := reg(rs1) srl bv_to_natural(reg(rs2)(27 to 31));
149
        when sp_func_sra => 
150
          reg(Rtype_rd) := reg(rs1) sra bv_to_natural(reg(rs2)(27 to 31));
151
        when sp_func_and => 
152
          reg(Rtype_rd) := reg(rs1) and reg(rs2);
153
        when sp_func_or => 
154
          reg(Rtype_rd) := reg(rs1) or reg(rs2);
155
        when sp_func_xor => 
156
          reg(Rtype_rd) := reg(rs1) xor reg(rs2);
157
        when sp_func_sequ =>
158
          reg(Rtype_rd) := set_if( reg(rs1) = reg(rs2) );
159
        when sp_func_sneu => 
160
          reg(Rtype_rd) := set_if( reg(rs1) /= reg(rs2) );
161
        when sp_func_sltu => 
162
          reg(Rtype_rd) := set_if( reg(rs1) < reg(rs2) );
163
        when sp_func_sgtu => 
164
          reg(Rtype_rd) := set_if( reg(rs1) > reg(rs2) );
165
        when sp_func_sleu => 
166
          reg(Rtype_rd) := set_if( reg(rs1) <= reg(rs2) );
167
        when sp_func_sgeu => 
168
          reg(Rtype_rd) := set_if( reg(rs1) >= reg(rs2) );
169
        when sp_func_seq => 
170
          reg(Rtype_rd) := set_if( reg(rs1) = reg(rs2) );
171
        when sp_func_sne => 
172
          reg(Rtype_rd) := set_if( reg(rs1) /= reg(rs2) );
173
        when sp_func_slt => 
174
          reg(Rtype_rd) := set_if( bv_lt(reg(rs1), reg(rs2)) );
175
        when sp_func_sgt => 
176
          reg(Rtype_rd) := set_if( bv_gt(reg(rs1), reg(rs2)) );
177
        when sp_func_sle => 
178
          reg(Rtype_rd) := set_if( bv_le(reg(rs1), reg(rs2)) );
179
        when sp_func_sge => 
180
          reg(Rtype_rd) := set_if( bv_ge(reg(rs1), reg(rs2)) );
181
        when sp_func_movi2s | sp_func_movs2i
182
          | sp_func_movf | sp_func_movd
183
          | sp_func_movfp2i | sp_func_movi2fp => 
184
          report sp_func_names(bv_to_natural(IR_sp_func))
185
            & " instruction not implemented" severity warning;
186
        when others =>
187
          report "undefined special instruction function" severity error;
188
      end case;
189
    end procedure execute_op_special;
190

    
191

    
192
    procedure execute_op_fparith is
193
    begin
194
      case IR_fp_func is
195
        when fp_func_mult | fp_func_multu | fp_func_div | fp_func_divu
196
          | fp_func_addf | fp_func_subf | fp_func_multf | fp_func_divf
197
          | fp_func_addd | fp_func_subd | fp_func_multd | fp_func_divd
198
          | fp_func_cvtf2d | fp_func_cvtf2i | fp_func_cvtd2f
199
          | fp_func_cvtd2i | fp_func_cvti2f | fp_func_cvti2d
200
          | fp_func_eqf | fp_func_nef | fp_func_ltf | fp_func_gtf
201
          | fp_func_lef | fp_func_gef | fp_func_eqd | fp_func_ned
202
          | fp_func_ltd | fp_func_gtd | fp_func_led | fp_func_ged =>
203
          report fp_func_names(bv_to_natural(IR_fp_func))
204
            & " instruction not implemented" severity warning;
205
        when others =>
206
          report "undefined floating point instruction function" severity error;
207
      end case;
208
    end procedure execute_op_fparith;
209

    
210

    
211
    procedure execute_load ( data_width : dlx_mem_width; unsigned : boolean ) is
212

    
213
      variable temp : dlx_bv_word;
214

    
215
      -- type for least-significant two bits of address
216
      subtype ls_2_addr_bits is bit_vector(1 downto 0);
217

    
218
    begin
219
      mem_addr_reg := reg(rs1) + bv_sext(IR_immed16, 32);
220
      bus_read(mem_addr_reg, data_width, '0', mem_data_reg);
221
      if To_bit(reset) = '1' then
222
        return;
223
      end if;
224
      case data_width is
225
        when dlx_mem_width_byte =>
226
          case ls_2_addr_bits'(mem_addr_reg(1 downto 0)) is
227
            when B"00" =>
228
              temp(0 to 7) := mem_data_reg(0 to 7);
229
            when B"01" =>
230
              temp(0 to 7) := mem_data_reg(8 to 15);
231
            when B"10" =>
232
              temp(0 to 7) := mem_data_reg(16 to 23);
233
            when B"11" =>
234
              temp(0 to 7) := mem_data_reg(24 to 31);
235
          end case;
236
          if unsigned then
237
            reg(Itype_rd) := bv_zext(temp(0 to 7), 32);
238
          else
239
            reg(Itype_rd) := bv_sext(temp(0 to 7), 32);
240
          end if;
241
        when dlx_mem_width_halfword =>
242
          if mem_addr_reg(1) = '0' then
243
            temp(0 to 15) := mem_data_reg(0 to 15);
244
          else
245
            temp(0 to 15) := mem_data_reg(16 to 31);
246
          end if;
247
          if unsigned then
248
            reg(Itype_rd) := bv_zext(temp(0 to 15), 32);
249
          else
250
            reg(Itype_rd) := bv_sext(temp(0 to 15), 32);
251
          end if;
252
        when dlx_mem_width_word =>
253
          reg(Itype_rd) := mem_data_reg;
254
        when others =>
255
          null;
256
      end case;
257
    end procedure execute_load;
258

    
259

    
260
    procedure execute_store ( data_width : dlx_mem_width ) is
261

    
262
      variable temp : dlx_bv_word;
263

    
264
      -- type for least-significant two bits of address
265
      subtype ls_2_addr_bits is bit_vector(1 downto 0);
266

    
267
    begin
268
      mem_addr_reg := reg(rs1) + bv_sext(IR_immed16, 32);
269
      mem_data_reg := X"0000_0000";
270
      case data_width is
271
        when dlx_mem_width_byte =>
272
          case ls_2_addr_bits'(mem_addr_reg(1 downto 0)) is
273
            when B"00" =>
274
              mem_data_reg(0 to 7) := reg(Itype_rd)(0 to 7);
275
            when B"01" =>
276
              mem_data_reg(8 to 15) := reg(Itype_rd)(0 to 7);
277
            when B"10" =>
278
              mem_data_reg(16 to 23) := reg(Itype_rd)(0 to 7);
279
            when B"11" =>
280
              mem_data_reg(24 to 31) := reg(Itype_rd)(0 to 7);
281
          end case;
282
        when dlx_mem_width_halfword =>
283
          if mem_addr_reg(1) = '0' then
284
            mem_data_reg(0 to 15) := reg(Itype_rd)(0 to 15);
285
          else
286
            mem_data_reg(16 to 31) := reg(Itype_rd)(0 to 15);
287
          end if;
288
        when dlx_mem_width_word =>
289
          mem_data_reg := reg(Itype_rd);
290
        when others =>
291
          null;
292
      end case;
293
      bus_write(mem_addr_reg, data_width, mem_data_reg);
294
    end procedure execute_store;
295

    
296

    
297
  begin -- interpreter
298

    
299
    -- reset the processor
300
    d <= disabled_dlx_word;
301
    halt <= '0';
302
    write_enable <= '0';
303
    mem_enable <= '0';
304
    reg(0) := X"0000_0000";
305
    PC := X"0000_0000";
306
    instr_count := 0;
307
    wait on phi2 until falling_edge(phi2) and To_bit(reset) = '0';
308

    
309
    -- fetch-decode-execute loop
310
    while To_bit(reset) /= '1' loop
311
      -- fetch next instruction
312
      instr_count := instr_count + 1;
313
      if debug = msg_every_100_instructions and instr_count mod 100 = 0 then
314
        report "instruction count = " & natural'image(instr_count);
315
      end if;
316

    
317
      if debug >= msg_each_instruction then
318
        report "fetching instruction";
319
      end if;
320

    
321
      bus_read( address => PC, data_width => dlx_mem_width_word,
322
                instr_fetch => '1', data => IR );
323
      exit when To_bit(reset) = '1';
324

    
325
      if debug >= trace_each_instruction then
326
	disassemble(IR, disassembled_instr, disassembled_instr_len);
327
        report disassembled_instr(1 to disassembled_instr_len);
328
      end if;
329

    
330
      wait until rising_edge(phi1);
331

    
332
      -- increment the PC to point to the following instruction
333
      if debug = trace_each_step then
334
        report "incrementing PC";
335
      end if;
336

    
337
      PC := bv_addu(PC, PC_incr);
338

    
339
      -- decode the instruction
340
      if debug = trace_each_step then
341
        report "decoding instruction";
342
      end if;
343

    
344
      rs1 := bv_to_natural(IR_rs1);
345
      rs2 := bv_to_natural(IR_rs2);
346
      Itype_rd := bv_to_natural(IR_Itype_rd);
347
      Rtype_rd := bv_to_natural(IR_Rtype_rd);
348

    
349
      -- execute the instruction
350
      if debug = trace_each_step then
351
        report "executing instruction";
352
      end if;
353

    
354
      overflow := false;
355

    
356
      case IR_opcode is
357
        when op_special =>
358
          execute_op_special;
359
        when op_fparith =>
360
          execute_op_fparith;
361
        when op_j  => 
362
          PC := PC + bv_sext(IR_immed26, 32);
363
        when op_jal => 
364
          reg(link_reg) := PC;
365
          PC := PC + bv_sext(IR_immed26, 32);
366
        when op_jr => 
367
          PC := reg(rs1);
368
        when op_jalr => 
369
          reg(link_reg) := PC;
370
          PC := reg(rs1);
371
        when op_beqz => 
372
          if reg(rs1) = X"0000_0000" then
373
            PC := PC + bv_sext(IR_immed16, 32);
374
          end if;
375
        when op_bnez => 
376
          if reg(rs1) /= X"0000_0000" then
377
            PC := PC + bv_sext(IR_immed16, 32);
378
          end if;
379
        when op_addi =>
380
          bv_add(reg(rs1), bv_sext(IR_immed16, 32), reg(Itype_rd), overflow);
381
        when op_addui => 
382
          bv_addu(reg(rs1), bv_zext(IR_immed16, 32), reg(Itype_rd), overflow);
383
        when op_subi => 
384
          bv_sub(reg(rs1), bv_sext(IR_immed16, 32), reg(Itype_rd), overflow);
385
        when op_subui => 
386
          bv_subu(reg(rs1), bv_zext(IR_immed16, 32), reg(Itype_rd), overflow);
387
        when op_slli => 
388
          reg(Itype_rd) := reg(rs1) sll bv_to_natural(IR_immed16(11 to 15));
389
        when op_srli =>
390
          reg(Itype_rd) := reg(rs1) srl bv_to_natural(IR_immed16(11 to 15));
391
        when op_srai => 
392
          reg(Itype_rd) := reg(rs1) sra bv_to_natural(IR_immed16(11 to 15));
393
        when op_andi => 
394
          reg(Itype_rd) := reg(rs1) and bv_zext(IR_immed16, 32);
395
        when op_ori => 
396
          reg(Itype_rd) := reg(rs1) or bv_zext(IR_immed16, 32);
397
        when op_xori => 
398
          reg(Itype_rd) := reg(rs1) xor bv_zext(IR_immed16, 32);
399
        when op_lhi => 
400
          reg(Itype_rd) := IR_immed16 & X"0000";
401
        when op_sequi => 
402
          reg(Itype_rd) := set_if( reg(rs1) = bv_zext(IR_immed16, 32) );
403
        when op_sneui => 
404
          reg(Itype_rd) := set_if( reg(rs1) /= bv_zext(IR_immed16, 32) );
405
        when op_sltui => 
406
          reg(Itype_rd) := set_if( reg(rs1) < bv_zext(IR_immed16, 32) );
407
        when op_sgtui => 
408
          reg(Itype_rd) := set_if( reg(rs1) > bv_zext(IR_immed16, 32) );
409
        when op_sleui => 
410
          reg(Itype_rd) := set_if( reg(rs1) <= bv_zext(IR_immed16, 32) );
411
        when op_sgeui => 
412
          reg(Itype_rd) := set_if( reg(rs1) >= bv_zext(IR_immed16, 32) );
413
        when op_seqi => 
414
          reg(Itype_rd) := set_if( reg(rs1) = bv_sext(IR_immed16, 32) );
415
        when op_snei => 
416
          reg(Itype_rd) := set_if( reg(rs1) /= bv_sext(IR_immed16, 32) );
417
        when op_slti => 
418
          reg(Itype_rd) := set_if( bv_lt(reg(rs1), bv_sext(IR_immed16, 32)) );
419
        when op_sgti => 
420
          reg(Itype_rd) := set_if( bv_gt(reg(rs1), bv_sext(IR_immed16, 32)) );
421
        when op_slei => 
422
          reg(Itype_rd) := set_if( bv_le(reg(rs1), bv_sext(IR_immed16, 32)) );
423
        when op_sgei => 
424
          reg(Itype_rd) := set_if( bv_ge(reg(rs1), bv_sext(IR_immed16, 32)) );
425
        when op_trap =>
426
          report "TRAP instruction encountered, execution halted" severity note;
427
          halt <= '1' after Tpd_clk_out;
428
          wait until To_bit(reset) = '1';
429
          exit;
430
        when op_lb =>
431
          execute_load(data_width => dlx_mem_width_byte, unsigned => false);
432
          exit when To_bit(reset) = '1';
433
        when op_lh => 
434
          execute_load(data_width => dlx_mem_width_halfword, unsigned => false);
435
          exit when To_bit(reset) = '1';
436
        when op_lw => 
437
          execute_load(data_width => dlx_mem_width_word, unsigned => false);
438
          exit when To_bit(reset) = '1';
439
        when op_lbu => 
440
          execute_load(data_width => dlx_mem_width_byte, unsigned => true);
441
          exit when To_bit(reset) = '1';
442
        when op_lhu => 
443
          execute_load(data_width => dlx_mem_width_halfword, unsigned => true);
444
          exit when To_bit(reset) = '1';
445
        when op_sb => 
446
          execute_store ( data_width => dlx_mem_width_byte );
447
          exit when To_bit(reset) = '1';
448
        when op_sh => 
449
          execute_store ( data_width => dlx_mem_width_halfword );
450
          exit when To_bit(reset) = '1';
451
        when op_sw => 
452
          execute_store ( data_width => dlx_mem_width_word );
453
          exit when To_bit(reset) = '1';
454
        when op_rfe | op_bfpt | op_bfpf | op_lf | op_ld | op_sf | op_sd => 
455
          report opcode_names(bv_to_natural(IR_opcode))
456
            & " instruction not implemented" severity warning;
457
        when others =>
458
          report "undefined instruction" severity error;
459
      end case;
460

    
461
      -- fix up R0 in case it was overwritten
462
      reg(0) := X"0000_0000";
463

    
464
      -- overflow and divide-by-zero exception handing
465
      -- (not implemented)
466

    
467
      if debug = trace_each_step then
468
        report "end of execution";
469
      end if;
470

    
471
    end loop;
472
    -- loop is only exited when reset active:
473
    -- process interpreter starts again from beginning
474
  end process interpreter;
475

    
476
end architecture behavior;
(265-265/510)