OpenCores
URL https://opencores.org/ocsvn/tisc/tisc/trunk

Subversion Repositories tisc

[/] [tisc/] [web_uploads/] [tisc_sim.c] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 root
/* Vins Tisc CPU Core, 7th Nov 2001 */
2
 
3
/* implemented in C for starters, transferred to VHDL later... */
4
/* My first attempt at processor design, thanks to :- */
5
/* Tim Boscke - CPU8BIT2, Rokwell - 6502, Microchip - Pic */
6
/* Jien Chung Lo - EL405 , Steve Scott - Tisc, */
7
/* Giovanni Moretti - Intro to Asm */
8
/* Uses 12 bit program word, and 8 bit data memory */
9
/* but its not a pic (honest guv) */
10
 
11
/* 2 reg machine,accumulator based, with akku and index regs */
12
/* Harvard architecture, uses return x so as to eliminate need of pmem */
13
/* indirect instructions like 8051. */
14
/* pc is 10 bits, akku and idx are 8 bit. */
15
/* Zero flag checked and pc always incremented */
16
/* at end of each instruction. */
17
 
18
/* Has carry and zero flags, */
19
/* three addressing modes:- immediate, indirect and reg. */
20
/* seperate program and data memory for pipelining later... */
21
 
22
/* Instructions coded as thus:- */
23
 
24
/*
25
   ; Long instructions first - program jump.
26
   ; Both store return address for subroutine calls, 1 deep stack.
27
   00 xxxxxxxxxx jc pmem10 ; if c==1, stack = pc, pc <- pmem10, fi
28
   01 xxxxxxxxxx jz pmem10 ; if z==1, stack = pc, pc <- pmem10, fi
29
 
30
   ; Immediate ops
31
   ; bits 9 and 8 select what to do
32
   10 00 xxxxxxxx ld a,#imm8 ; a= imm8, c=0,
33
   10 01 xxxxxxxx adc a,#imm8 ; add with carry imm8, cy and z set
34
   10 10 xxxxxxxx adx ix,#imm8 ; add imm8 to idx reg, z=(a==0)
35
 
36
   ; Special op is method of reading pmem space/lookup table and sub return
37
   ; kind of load immediate - not sure how many states this will need
38
   10 11 xxxxxxxx ret a,#imm8 ; a= imm8, pc = stack
39
 
40
   ; Indirect and alu ops
41
   ; bit 9 selects indirect or alu ops
42
 
43
   ; Indirect - bits 7 and 8 select what to do
44
   11 0 0 0 xxxxxxx ld a,[ix] ; load a indirect data mem
45
   11 0 0 1 xxxxxxx st [ix],a ; store a indirect data mem
46
 
47
   ; register register
48
   11 0 1 0 xxxxxxx tax ; x = a,
49
   11 0 1 1 xxxxxxx txa ; a = x
50
 
51
   ; Arithmetic ops use indirect addressing
52
   ; all alu ops indirect, bits 7 and 8 select alu op.
53
   11 1 00 xxxxxxx add a,[ix] ; add with carry
54
   11 1 01 xxxxxxx sub a,[ix] ; sub with carry as borrow
55
   11 1 10 xxxxxxx and a,[ix] ; and mem contents into a
56
   11 1 11 xxxxxxx nor a,[ix] ; nor
57
 
58
 */
59
 
60
/* Further work:- since some indirect, register and alu ops */
61
/* dont use all of the word, we could do the following:-
62
 
63
   1) Implement dual instructions in a single 12 bit instruction word.
64
   2) Extend indirect addressing to use offset.
65
   3) Increase oip code functionality.
66
 
67
   Do this later - get it working first using small nostates.
68
 */
69
#include <stdlib.h>
70
#include <stdio.h>
71
/* Non Ansi - used for keypress */
72
#include <conio.h>
73
 
74
/* Vins handy defines */
75
 
76
#define bit(x) (1 << (x))
77
#define getbit(x, y) ((x & bit(y)) >> y)
78
#define setbit(x, y) ((x) & bit(y))
79
#define clrbit(x, y) ((x) & ~bit(y))
80
 
81
/* Mem bit widths */
82
#define DMEMWIDTH (8)
83
#define PMEMWIDTH (10)
84
 
85
/* Make a few macros for carry access */
86
/* not needed in hdl */
87
#define CY getbit(akku, 8)
88
 
89
/* VHDL take offs */
90
#define NINETO0 (0x3FF)
91
#define SEVENTO0 (0xFF)
92
 
93
/* Define instructions */
94
/* jcc is b00 xx xxxx xxxx */
95
#define JC (0x000)
96
/* ldx is b01 xx xxxx xxxx */
97
#define JZ (0x400)
98
/* Immediate instructions - b10 xx xxxx xxxx */
99
#define IMM (0x800)
100
/* indirect and alu ops - b11 xx xxxx xxxx */
101
#define IND (0xC00)
102
/* Reg - Reg */
103
#define REG IND
104
 
105
/* Subset instructions */
106
/* Immediate subtypes */
107
#define LDA (0x000)
108
#define ADC (0x100)
109
#define ADX (0x200)
110
#define RET (0x300)
111
 
112
/* ALU indirect ops */
113
/* add - b 00 xxxxxxx */
114
#define ADD (0x000)
115
/* sub - b 01 xxxxxxx */
116
#define SUB (0x080)
117
/* and - b 10 xxxxxxx */
118
#define AND (0x100)
119
/* nor - b 11 xxxxxxx */
120
#define NOR (0x180)
121
 
122
/* Reg to Reg */
123
/* transfer a to x - b1101 0000 0000*/
124
#define TAX (0xD00)
125
/* transfer x to a - b1101 1000 0000*/
126
#define TXA (0xD80)
127
 
128
/* Indirect Ops ld/st */
129
/* ld a,[ix] - b1100 0xxx xxxx ld */
130
#define LDAX (0xC00)
131
/* st [ix],a - b1100 1xxx xxxx st */
132
#define STAX (0xC80)
133
 
134
/* create special data type */
135
typedef unsigned short UNSIGNED10;
136
typedef unsigned short AKKU9;
137
typedef unsigned char BYTE;
138
typedef unsigned char BIT;
139
 
140
/* data memory */
141
BYTE dmem[2 ^ DMEMWIDTH]; /* program memory */
142
UNSIGNED10 pmem[2 ^ PMEMWIDTH];
143
 
144
/* main program start */
145
void main(int argc, char **argv)
146
{
147
  UNSIGNED10 PC; /* Program counter is 10 bit */
148
  UNSIGNED10 stack; /* stack is also 10 bit */
149
  UNSIGNED10 instr; /* working data bus */
150
 
151
  BIT Z; /* Flags */
152
 
153
/* 9 bit accumulator */
154
/* bit 9 is cy */
155
  AKKU9 akku;
156
 
157
/* State, temp and index registers */
158
  BYTE state, temp, ix;
159
 
160
/* reset - only reset PC & States in real CPU?*/
161
  PC = 0; akku = 0;
162
  state = 0; ix = 0; Z = 0;
163
 
164
  printf("\nPress 'q' to quit.\n");
165
 
166
/* Load a simple program - just an opcode test*/
167
  pmem[0] = IMM | LDA | 0x55;
168
  pmem[1] = REG | TAX;
169
  pmem[2] = IMM | LDA | 0xAA;
170
  pmem[3] = IND | STAX; /* Store A (0xaa) at 0x55 */
171
  pmem[4] = IND | NOR; /* Zero A */
172
  pmem[5] = IMM | LDA | 0xff;
173
  pmem[6] = IMM | ADC | 0x01; /* Set carry */
174
  pmem[7] = JC | 0x10 - 1; /* start again of overflow - remember 1 less*/
175
  pmem[0x10] = IMM | LDA | 0x00; /* clear A and zero flag */
176
  pmem[0x11] = JZ | 0x20 - 1; /* jump to 0x21 - remember 1 less */
177
/* should now return here with val in A */
178
  pmem[0x12] = IND | STAX; /* Store A (0xaa) at 0x55 */
179
  pmem[0x13] = IMM | LDA | 0x00; /* clear A and zero flag */
180
  pmem[0x14] = JZ | 0x21 - 1; /* jump to 0x21 - remember 1 less */
181
/* should now return here with val in A */
182
  pmem[0x15] = IND | STAX; /* Store A at 0x55 */
183
  pmem[0x16] = IMM | LDA | 0x00; /* clear A and zero flag */
184
  pmem[0x17] = JZ | 0x00; /* Start again, 1 less remember */
185
 
186
/* Lookup table */
187
  pmem[0x20] = IMM | RET | 0x99;
188
  pmem[0x21] = IMM | RET | 0x81;
189
 
190
/* Main fetch-decode-execute-store cycle */
191
  while (1) /* main state machine loop */
192
 
193
    { /* fetch */
194
      instr = pmem[PC];
195
 
196
/* now single step through program */
197
      printf("mem\top\takku\tix\tStack\ttemp\tState\tC Z\n");
198
 
199
      printf("%03X\t%03X\t%02X\t%02X\t%03X\t%02X\t%02X\t%c %c\n",
200
             PC, instr, akku & 0xff, ix, stack, temp, state, CY ? '1' : '0', Z ? '1' : '0');
201
 
202
/* Non Ansi but you know what I mean... */
203
      while (!_kbhit()) ;
204
      if (tolower(_getch()) == 'q') return; /* Quit if 'q' pressed */
205
 
206
/* Initial decode */
207
      switch (instr & (bit(11) | bit(10)))
208
        {
209
        case JC: /* jump if cary set */
210
          if (CY)
211
            {
212
/* save return address */
213
              stack = PC;
214
 
215
/* Set PC to new value */
216
/* remember it also increments */
217
              PC = instr & NINETO0;
218
            }
219
 
220
          break;
221
 
222
        case JZ:
223
          if (Z)
224
            {
225
/* Save return address */
226
              stack = PC;
227
 
228
/* Set PC to new value */
229
/* remember it also increments */
230
 
231
              PC = instr & NINETO0;
232
            }
233
 
234
          break;
235
 
236
        case IMM:
237
/* decode immediate instruction */
238
          switch (instr & (bit(8) | bit(9)))
239
            {
240
            case LDA:
241
              akku = (instr & SEVENTO0);
242
              break;
243
 
244
            case ADC:
245
              akku += (instr & SEVENTO0);
246
/* CY set on overflow */
247
              break;
248
 
249
            case ADX:
250
              ix += (instr & SEVENTO0);
251
              break;
252
 
253
            case RET:
254
              akku = (instr & SEVENTO0);
255
/* return stack */
256
              PC = stack;
257
              break;
258
 
259
            default: /* shoudl never get here */
260
              ;
261
            } /* end of imm subtype decode */
262
 
263
          break;
264
 
265
        case IND: /* All these are indirect */
266
/* Decode either alu or load/store instr */
267
          if (instr & bit(9)) /* ALU add, sub, and, or*/
268
 
269
            { /* get temp value of mem location */
270
/* might include disp7 here, ignore for min */
271
              temp = dmem[ix];
272
 
273
/* decode indirect alu instruction */
274
              switch (instr & (bit(8) | bit(7)))
275
                {
276
                case ADD:
277
                  akku += temp;
278
                  break;
279
 
280
                case SUB:
281
/* CY acts as borrow if underflow */
282
                  akku -= temp;
283
                  break;
284
 
285
                case AND:
286
                  akku &= temp;
287
                  break;
288
 
289
                case NOR:
290
                  akku = ~(akku | temp) & SEVENTO0;
291
                  break;
292
 
293
                default: /* shoudl never get here */
294
                  ;
295
                } /* end of imm subtye decode */
296
            }
297
          else                            /* ld/store indirect & reg - reg*/
298
            {
299
              if (instr & bit(8)) /* reg - reg */
300
                {
301
                  if (bit(7)) /* tax */
302
                    {
303
                      ix = akku & SEVENTO0;
304
                    }
305
                  else /* txa */
306
                    {
307
                      akku = ix;
308
                    }
309
                }
310
              else /* ld/store */
311
                {
312
                  if (bit(7)) /* store */
313
                    { /* not sure how to do this */
314
                      dmem[ix] = akku & SEVENTO0;
315
                    }
316
                  else /* load */
317
                    {
318
                      akku = dmem[ix];
319
                    }
320
                } /* reg - reg if */
321
            } /* alu or indirect if */
322
 
323
          break; /* alu/ind load/store switch */
324
 
325
        default:
326
          ; /* shouldnt get here */
327
        }
328
 
329
/* PC always incremented */
330
      PC += 1;
331
/* set zero flag */
332
      Z = (akku == 0);
333
    } /* main while loop */
334
} /* end of prog */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.