1 |
3 |
dgisselq |
///////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Filename: cpudefs.v
|
4 |
|
|
//
|
5 |
|
|
// Project: OpenArty, an entirely open SoC based upon the Arty platform
|
6 |
|
|
//
|
7 |
|
|
// Purpose: Some architectures have some needs, others have other needs.
|
8 |
|
|
// Some of my projects need a Zip CPU with pipelining, others
|
9 |
|
|
// can't handle the timing required to get the answer from the ALU
|
10 |
|
|
// back into the input for the ALU. As each different projects has
|
11 |
|
|
// different needs, I can either 1) reconfigure my entire baseline prior
|
12 |
|
|
// to building each project, or 2) host a configuration file which contains
|
13 |
|
|
// the information regarding each baseline. This file is that
|
14 |
|
|
// configuration file. It controls how the CPU (not the system,
|
15 |
|
|
// peripherals, or other) is defined and implemented. Several options
|
16 |
|
|
// are available within here, making the Zip CPU pipelined or not,
|
17 |
|
|
// able to handle a faster clock with more stalls or a slower clock with
|
18 |
|
|
// no stalls, etc.
|
19 |
|
|
//
|
20 |
|
|
// This file encapsulates those control options.
|
21 |
|
|
//
|
22 |
|
|
// The number of LUTs the Zip CPU uses varies dramatically with the
|
23 |
|
|
// options defined in this file.
|
24 |
|
|
//
|
25 |
|
|
//
|
26 |
|
|
// OpenArty comments:
|
27 |
|
|
// My goal on the OpenArty is going to be using the CPU to its fullest
|
28 |
|
|
// extent. All features shall be turned on if they exist, full pipelines,
|
29 |
|
|
// multiplies, divides, and hopefully even the 200MHz clock. This file
|
30 |
|
|
// reflects that purpose.
|
31 |
|
|
//
|
32 |
|
|
//
|
33 |
|
|
// Creator: Dan Gisselquist, Ph.D.
|
34 |
|
|
// Gisselquist Technology, LLC
|
35 |
|
|
//
|
36 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
37 |
|
|
//
|
38 |
|
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
39 |
|
|
//
|
40 |
|
|
// This program is free software (firmware): you can redistribute it and/or
|
41 |
|
|
// modify it under the terms of the GNU General Public License as published
|
42 |
|
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
43 |
|
|
// your option) any later version.
|
44 |
|
|
//
|
45 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
46 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
47 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
48 |
|
|
// for more details.
|
49 |
|
|
//
|
50 |
|
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
51 |
|
|
// http://www.gnu.org/licenses/gpl.html
|
52 |
|
|
//
|
53 |
|
|
//
|
54 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
55 |
|
|
`ifndef CPUDEFS_H
|
56 |
|
|
`define CPUDEFS_H
|
57 |
|
|
//
|
58 |
|
|
//
|
59 |
|
|
// The first couple options control the Zip CPU instruction set, and how
|
60 |
|
|
// it handles various instructions within the set:
|
61 |
|
|
//
|
62 |
|
|
//
|
63 |
|
|
// OPT_ILLEGAL_INSTRUCTION is part of a new section of code that is supposed
|
64 |
|
|
// to recognize illegal instructions and interrupt the CPU whenever one such
|
65 |
|
|
// instruction is encountered. The goal is to create a soft floating point
|
66 |
|
|
// unit via this approach, that can then be replaced with a true floating point
|
67 |
|
|
// unit. As I'm not there yet, it just catches illegal instructions and
|
68 |
|
|
// interrupts the CPU on any such instruction--when defined. Otherwise,
|
69 |
|
|
// illegal instructions are quietly ignored and their behaviour is ...
|
70 |
|
|
// undefined. (Many get treated like NOOPs ...)
|
71 |
|
|
//
|
72 |
32 |
dgisselq |
// I recommend setting this flag so highly, that I'm likely going to remove
|
73 |
|
|
// the option to turn this off in future versions of this CPU.
|
74 |
3 |
dgisselq |
//
|
75 |
|
|
`define OPT_ILLEGAL_INSTRUCTION
|
76 |
|
|
//
|
77 |
|
|
//
|
78 |
|
|
//
|
79 |
|
|
// OPT_MULTIPLY controls whether or not the multiply is built and included
|
80 |
|
|
// in the ALU by default. Set this option and a parameter will be set that
|
81 |
|
|
// includes the multiply. (This parameter may still be overridden, as with
|
82 |
|
|
// any parameter ...) If the multiply is not included and
|
83 |
|
|
// OPT_ILLEGAL_INSTRUCTION is set, then the multiply will create an illegal
|
84 |
|
|
// instruction that will then trip the illegal instruction trap.
|
85 |
|
|
//
|
86 |
|
|
//
|
87 |
|
|
`define OPT_MULTIPLY 1
|
88 |
|
|
//
|
89 |
|
|
//
|
90 |
|
|
//
|
91 |
|
|
// OPT_DIVIDE controls whether or not the divide instruction is built and
|
92 |
|
|
// included into the ZipCPU by default. Set this option and a parameter will
|
93 |
|
|
// be set that causes the divide unit to be included. (This parameter may
|
94 |
|
|
// still be overridden, as with any parameter ...) If the divide is not
|
95 |
|
|
// included and OPT_ILLEGAL_INSTRUCTION is set, then the multiply will create
|
96 |
|
|
// an illegal instruction exception that will send the CPU into supervisor
|
97 |
|
|
// mode.
|
98 |
|
|
//
|
99 |
|
|
//
|
100 |
30 |
dgisselq |
`define OPT_DIVIDE
|
101 |
3 |
dgisselq |
//
|
102 |
|
|
//
|
103 |
|
|
//
|
104 |
|
|
// OPT_IMPLEMENT_FPU will (one day) control whether or not the floating point
|
105 |
|
|
// unit (once I have one) is built and included into the ZipCPU by default.
|
106 |
|
|
// At that time, if this option is set then a parameter will be set that
|
107 |
|
|
// causes the floating point unit to be included. (This parameter may
|
108 |
|
|
// still be overridden, as with any parameter ...) If the floating point unit
|
109 |
|
|
// is not included and OPT_ILLEGAL_INSTRUCTION is set, then as with the
|
110 |
|
|
// multiply and divide any floating point instruction will result in an illegal
|
111 |
|
|
// instruction exception that will send the CPU into supervisor mode.
|
112 |
|
|
//
|
113 |
|
|
//
|
114 |
|
|
// `define OPT_IMPLEMENT_FPU
|
115 |
|
|
//
|
116 |
|
|
//
|
117 |
|
|
//
|
118 |
|
|
// OPT_NEW_INSTRUCTION_SET controls whether or not the new instruction set
|
119 |
|
|
// is in use. The new instruction set contains space for floating point
|
120 |
|
|
// operations, signed and unsigned divide instructions, as well as bit reversal
|
121 |
|
|
// and ... at least two other operations yet to be defined. The decoder alone
|
122 |
|
|
// uses about 70 fewer LUTs, although in practice this works out to 12 fewer
|
123 |
|
|
// when all works out in the wash. Further, floating point and divide
|
124 |
|
|
// instructions will cause an illegal instruction exception if they are not
|
125 |
|
|
// implemented--so software capability can be built to use these instructions
|
126 |
|
|
// immediately, even if the hardware is not yet ready.
|
127 |
|
|
//
|
128 |
|
|
// This option is likely to go away in the future, obsoleting the previous
|
129 |
|
|
// instruction set, so I recommend setting this option and switching to the
|
130 |
|
|
// new instruction set as soon as possible.
|
131 |
|
|
//
|
132 |
|
|
`define OPT_NEW_INSTRUCTION_SET
|
133 |
|
|
//
|
134 |
|
|
//
|
135 |
|
|
//
|
136 |
|
|
//
|
137 |
|
|
//
|
138 |
|
|
//
|
139 |
|
|
// OPT_SINGLE_FETCH controls whether or not the prefetch has a cache, and
|
140 |
|
|
// whether or not it can issue one instruction per clock. When set, the
|
141 |
|
|
// prefetch has no cache, and only one instruction is fetched at a time.
|
142 |
|
|
// This effectively sets the CPU so that only one instruction is ever
|
143 |
|
|
// in the pipeline at once, and hence you may think of this as a "kill
|
144 |
|
|
// pipeline" option. However, since the pipelined fetch component uses so
|
145 |
|
|
// much area on the FPGA, this is an important option to use in trimming down
|
146 |
|
|
// used area if necessary. Hence, it needs to be maintained for that purpose.
|
147 |
|
|
// Be aware, though, it will drop your performance by a factor between 2x and
|
148 |
|
|
// 3x.
|
149 |
|
|
//
|
150 |
|
|
// We can either pipeline our fetches, or issue one fetch at a time. Pipelined
|
151 |
|
|
// fetches are more complicated and therefore use more FPGA resources, while
|
152 |
|
|
// single fetches will cause the CPU to stall for about 5 stalls each
|
153 |
|
|
// instruction cycle, effectively reducing the instruction count per clock to
|
154 |
|
|
// about 0.2. However, the area cost may be worth it. Consider:
|
155 |
|
|
//
|
156 |
|
|
// Slice LUTs ZipSystem ZipCPU
|
157 |
|
|
// Single Fetching 2521 1734
|
158 |
|
|
// Pipelined fetching 2796 2046
|
159 |
|
|
// (These numbers may be dated, but should still be representative ...)
|
160 |
|
|
//
|
161 |
|
|
// I recommend only defining this if you "need" to, if area is tight and
|
162 |
|
|
// speed isn't as important. Otherwise, just leave this undefined.
|
163 |
|
|
//
|
164 |
|
|
// `define OPT_SINGLE_FETCH
|
165 |
|
|
//
|
166 |
|
|
//
|
167 |
|
|
//
|
168 |
|
|
// The next several options are pipeline optimization options. They make no
|
169 |
|
|
// sense in a single instruction fetch mode, hence we #ifndef them so they
|
170 |
|
|
// are only defined if we are in a full pipelined mode (i.e. OPT_SINGLE_FETCH
|
171 |
|
|
// is not defined).
|
172 |
|
|
//
|
173 |
|
|
`ifndef OPT_SINGLE_FETCH
|
174 |
|
|
//
|
175 |
|
|
//
|
176 |
|
|
//
|
177 |
|
|
// OPT_PIPELINED is the natural result and opposite of using the single
|
178 |
|
|
// instruction fetch unit. If you are not using that unit, the ZipCPU will
|
179 |
|
|
// be pipelined. The option is defined here more for readability than
|
180 |
|
|
// anything else, since OPT_PIPELINED makes more sense than OPT_SINGLE_FETCH,
|
181 |
|
|
// well ... that and it does a better job of explaining what is going on.
|
182 |
|
|
//
|
183 |
|
|
// In other words, leave this define alone--lest you break the ZipCPU.
|
184 |
|
|
//
|
185 |
|
|
`define OPT_PIPELINED
|
186 |
|
|
//
|
187 |
|
|
//
|
188 |
|
|
//
|
189 |
|
|
// OPT_TRADITIONAL_PFCACHE allows you to switch between one of two prefetch
|
190 |
|
|
// caches. If enabled, a more traditional cache is implemented. This more
|
191 |
|
|
// traditional cache (currently) uses many more LUTs, but it also reduces
|
192 |
|
|
// the stall count tremendously over the alternative hacked pipeline cache.
|
193 |
|
|
// (The traditional pfcache is also pipelined, whereas the pipeline cache
|
194 |
|
|
// implements a windowed approach to caching.)
|
195 |
|
|
//
|
196 |
|
|
// If you have the fabric to support this option, I recommend including it.
|
197 |
|
|
//
|
198 |
|
|
`define OPT_TRADITIONAL_PFCACHE
|
199 |
|
|
//
|
200 |
|
|
//
|
201 |
|
|
//
|
202 |
|
|
// OPT_EARLY_BRANCHING is an attempt to execute a BRA statement as early
|
203 |
|
|
// as possible, to avoid as many pipeline stalls on a branch as possible.
|
204 |
|
|
// It's not tremendously successful yet--BRA's still suffer stalls,
|
205 |
|
|
// but I intend to keep working on this approach until the number of stalls
|
206 |
|
|
// gets down to one or (ideally) zero. (With the OPT_TRADITIONAL_PFCACHE, this
|
207 |
|
|
// gets down to a single stall cycle ...) That way a "BRA" can be used as the
|
208 |
|
|
// compiler's branch prediction optimizer: BRA's barely stall, while branches
|
209 |
|
|
// on conditions will always suffer about 4 stall cycles or so.
|
210 |
|
|
//
|
211 |
|
|
// I recommend setting this flag, so as to turn early branching on.
|
212 |
|
|
//
|
213 |
|
|
`define OPT_EARLY_BRANCHING
|
214 |
|
|
//
|
215 |
|
|
//
|
216 |
|
|
//
|
217 |
|
|
// OPT_PIPELINED_BUS_ACCESS controls whether or not LOD/STO instructions
|
218 |
|
|
// can take advantaged of pipelined bus instructions. To be eligible, the
|
219 |
|
|
// operations must be identical (cannot pipeline loads and stores, just loads
|
220 |
|
|
// only or stores only), and the addresses must either be identical or one up
|
221 |
|
|
// from the previous address. Further, the load/store string must all have
|
222 |
|
|
// the same conditional. This approach gains the must use, in my humble
|
223 |
|
|
// opinion, when saving registers to or restoring registers from the stack
|
224 |
|
|
// at the beginning/end of a procedure, or when doing a context swap.
|
225 |
|
|
//
|
226 |
|
|
// I recommend setting this flag, for performance reasons, especially if your
|
227 |
|
|
// wishbone bus can handle pipelined bus accesses.
|
228 |
|
|
//
|
229 |
|
|
`define OPT_PIPELINED_BUS_ACCESS
|
230 |
|
|
//
|
231 |
|
|
//
|
232 |
|
|
//
|
233 |
|
|
`ifdef OPT_NEW_INSTRUCTION_SET
|
234 |
|
|
//
|
235 |
|
|
//
|
236 |
|
|
//
|
237 |
|
|
// The new instruction set also defines a set of very long instruction words.
|
238 |
|
|
// Well, calling them "very long" instruction words is probably a misnomer,
|
239 |
|
|
// although we're going to do it. They're really 2x16-bit instructions---
|
240 |
|
|
// instruction words that pack two instructions into one word. (2x14 bit
|
241 |
|
|
// really--'cause you need a bit to note the instruction is a 2x instruction,
|
242 |
|
|
// and then 3-bits for the condition codes ...) Set OPT_VLIW to include these
|
243 |
|
|
// double instructions as part of the new instruction set. These allow a single
|
244 |
|
|
// instruction to contain two instructions within. These instructions are
|
245 |
|
|
// designed to get more code density from the instruction set, and to hopefully
|
246 |
|
|
// take some pain off of the performance of the pre-fetch and instruction cache.
|
247 |
|
|
//
|
248 |
|
|
// These new instructions, however, also necessitate a change in the Zip
|
249 |
|
|
// CPU--the Zip CPU can no longer execute instructions atomically. It must
|
250 |
|
|
// now execute non-VLIW instructions, or VLIW instruction pairs, atomically.
|
251 |
|
|
// This logic has been added into the ZipCPU, but it has not (yet) been
|
252 |
|
|
// tested thoroughly.
|
253 |
|
|
//
|
254 |
|
|
// Oh, and the assembler, the debugger, and the object file dumper, and the
|
255 |
|
|
// simulator all need to be updated as well ....
|
256 |
|
|
//
|
257 |
|
|
`define OPT_VLIW
|
258 |
|
|
//
|
259 |
|
|
//
|
260 |
|
|
`endif // OPT_NEW_INSTRUCTION_SET
|
261 |
|
|
//
|
262 |
|
|
//
|
263 |
|
|
`endif // OPT_SINGLE_FETCH
|
264 |
|
|
//
|
265 |
|
|
//
|
266 |
|
|
//
|
267 |
|
|
// Now let's talk about peripherals for a moment. These next two defines
|
268 |
|
|
// control whether the DMA controller is included in the Zip System, and
|
269 |
|
|
// whether or not the 8 accounting timers are also included. Set these to
|
270 |
|
|
// include the respective peripherals, comment them out not to.
|
271 |
|
|
//
|
272 |
|
|
`define INCLUDE_DMA_CONTROLLER
|
273 |
|
|
`define INCLUDE_ACCOUNTING_COUNTERS
|
274 |
|
|
//
|
275 |
|
|
//
|
276 |
30 |
dgisselq |
`define DEBUG_SCOPE
|
277 |
3 |
dgisselq |
//
|
278 |
|
|
`endif // CPUDEFS_H
|