Line 22... |
Line 22... |
// The number of LUTs the Zip CPU uses varies dramatically with the
|
// The number of LUTs the Zip CPU uses varies dramatically with the
|
// options defined in this file.
|
// options defined in this file.
|
//
|
//
|
//
|
//
|
// Creator: Dan Gisselquist, Ph.D.
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Tecnology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
//
|
//
|
Line 51... |
Line 51... |
//
|
//
|
// The first couple options control the Zip CPU instruction set, and how
|
// The first couple options control the Zip CPU instruction set, and how
|
// it handles various instructions within the set:
|
// it handles various instructions within the set:
|
//
|
//
|
//
|
//
|
// OPT_CONDITIONAL_FLAGS controls whether or not a conditional instruction
|
|
// is allowed to set flags. If conditional instructions can set flags, then
|
|
// strings of conditional instructions will die whenever a flag setting
|
|
// instruction is executed. If they cannot, then you can execute a string
|
|
// of functions with no further conditions in them. Set this flag to enable
|
|
// strings of instructions, as these can be a lot cheaper than the pipeline
|
|
// stalls associated with a conditional branch.
|
|
//
|
|
// This option will likely be changed in the future so that "CMP" and "TST"
|
|
// instructions set the flags even if they are conditional, to allow multiple
|
|
// conditions to be tested at once.
|
|
//
|
|
// I recommend setting this flag
|
|
//
|
|
`define OPT_CONDITIONAL_FLAGS
|
|
//
|
|
//
|
|
//
|
|
// OPT_ILLEGAL_INSTRUCTION is part of a new section of code that is supposed
|
// OPT_ILLEGAL_INSTRUCTION is part of a new section of code that is supposed
|
// to recognize illegal instructions and interrupt the CPU whenever one such
|
// to recognize illegal instructions and interrupt the CPU whenever one such
|
// instruction is encountered. The goal is to create a soft floating point
|
// instruction is encountered. The goal is to create a soft floating point
|
// unit via this approach, that can then be replaced with a true floating point
|
// unit via this approach, that can then be replaced with a true floating point
|
// unit. As I'm not there yet, it just catches illegal instructions and
|
// unit. As I'm not there yet, it just catches illegal instructions and
|
Line 97... |
Line 79... |
//
|
//
|
`define OPT_MULTIPLY
|
`define OPT_MULTIPLY
|
//
|
//
|
//
|
//
|
//
|
//
|
|
// OPT_DIVIDE controls whether or not the divide instruction is built and
|
|
// included into the ZipCPU by default. Set this option and a parameter will
|
|
// be set that causes the divide unit to be included. (This parameter may
|
|
// still be overridden, as with any parameter ...) If the divide is not
|
|
// included and OPT_ILLEGAL_INSTRUCTION is set, then the multiply will create
|
|
// an illegal instruction exception that will send the CPU into supervisor
|
|
// mode.
|
|
//
|
|
//
|
|
`define OPT_DIVIDE
|
|
//
|
|
//
|
|
//
|
|
// OPT_IMPLEMENT_FPU will (one day) control whether or not the floating point
|
|
// unit (once I have one) is built and included into the ZipCPU by default.
|
|
// At that time, if this option is set then a parameter will be set that
|
|
// causes the floating point unit to be included. (This parameter may
|
|
// still be overridden, as with any parameter ...) If the floating point unit
|
|
// is not included and OPT_ILLEGAL_INSTRUCTION is set, then as with the
|
|
// multiply and divide any floating point instruction will result in an illegal
|
|
// instruction exception that will send the CPU into supervisor mode.
|
|
//
|
|
//
|
|
// `define OPT_IMPLEMENT_FPU
|
|
//
|
|
//
|
|
//
|
|
// OPT_NEW_INSTRUCTION_SET controls whether or not the new instruction set
|
|
// is in use. The new instruction set contains space for floating point
|
|
// operations, signed and unsigned divide instructions, as well as bit reversal
|
|
// and ... at least two other operations yet to be defined. The decoder alone
|
|
// uses about 70 fewer LUTs, although in practice this works out to 12 fewer
|
|
// when all works out in the wash. Further, floating point and divide
|
|
// instructions will cause an illegal instruction exception if they are not
|
|
// implemented--so software capability can be built to use these instructions
|
|
// immediately, even if the hardware is not yet ready.
|
|
//
|
|
// This option is likely to go away in the future, obsoleting the previous
|
|
// instruction set, so I recommend setting this option and switching to the
|
|
// new instruction set as soon as possible.
|
|
//
|
|
`define OPT_NEW_INSTRUCTION_SET
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
// OPT_SINGLE_FETCH controls whether or not the prefetch has a cache, and
|
// OPT_SINGLE_FETCH controls whether or not the prefetch has a cache, and
|
// whether or not it can issue one instruction per clock. When set, the
|
// whether or not it can issue one instruction per clock. When set, the
|
// prefetch has no cache, and only one instruction is fetched at a time.
|
// prefetch has no cache, and only one instruction is fetched at a time.
|
// This effectively sets the CPU so that only one instruction is ever
|
// This effectively sets the CPU so that only one instruction is ever
|
// in the pipeline at once, and hence you may think of this as a "kill
|
// in the pipeline at once, and hence you may think of this as a "kill
|
Line 135... |
Line 165... |
//
|
//
|
`ifndef OPT_SINGLE_FETCH
|
`ifndef OPT_SINGLE_FETCH
|
//
|
//
|
//
|
//
|
//
|
//
|
// OPT_PRECLEAR_BUS allows an upcoming, unconditional, LOD/STO instruction
|
// OPT_PIPELINED is the natural result and opposite of using the single
|
// to kick the prefetch off the memory bus so that the LOD/STO instruction may
|
// instruction fetch unit. If you are not using that unit, the ZipCPU will
|
// use the bus without waiting for the prefetch cycle to complete. While it
|
// be pipelined. The option is defined here more for readability than
|
// sounds like this should speed things up, it isn't clear that it speeds up
|
// anything else, since OPT_PIPELINED makes more sense than OPT_SINGLE_FETCH,
|
// programs that much--often the bus gets precleared for the LOD/STO, only
|
// well ... that and it does a better job of explaining what is going on.
|
// to have the next instruction stall because it wasn't loaded in time.
|
//
|
|
// In other words, leave this define alone--lest you break the ZipCPU.
|
|
//
|
|
`define OPT_PIPELINED
|
//
|
//
|
// While I recommend setting this flag, that recommendation may change in the
|
|
// future.
|
|
//
|
//
|
`define OPT_PRECLEAR_BUS
|
//
|
|
// OPT_TRADITIONAL_PFCACHE allows you to switch between one of two prefetch
|
|
// caches. If enabled, a more traditional cache is implemented. This more
|
|
// traditional cache (currently) uses many more LUTs, but it also reduces
|
|
// the stall count tremendously over the alternative hacked pipeline cache.
|
|
// (The traditional pfcache is also pipelined, whereas the pipeline cache
|
|
// implements a windowed approach to caching.)
|
|
//
|
|
// If you have the fabric to support this option, I recommend including it.
|
|
//
|
|
`define OPT_TRADITIONAL_PFCACHE
|
//
|
//
|
//
|
//
|
//
|
//
|
// OPT_EARLY_BRANCHING is an attempt to execute a BRA statement as early
|
// OPT_EARLY_BRANCHING is an attempt to execute a BRA statement as early
|
// as possible, to avoid as many pipeline stalls on a branch as possible.
|
// as possible, to avoid as many pipeline stalls on a branch as possible.
|
// It's not tremendously successful yet--BRA's suffer 3 stalls instead of 5,
|
// It's not tremendously successful yet--BRA's still suffer stalls,
|
// but I intend to keep working on this approach until the number of stalls
|
// but I intend to keep working on this approach until the number of stalls
|
// gets down to one or (ideally) zero. That way a "BRA" can be used as the
|
// gets down to one or (ideally) zero. (With the OPT_TRADITIONAL_PFCACHE, this
|
// compiler's branch prediction optimizer: BRA's don't stall, while branches on
|
// gets down to a single stall cycle ...) That way a "BRA" can be used as the
|
// conditions will always suffer about 5 stalls or so.
|
// compiler's branch prediction optimizer: BRA's barely stall, while branches
|
|
// on conditions will always suffer about 4 stall cycles or so.
|
//
|
//
|
// I recommend setting this flag, so as to turn early branching on.
|
// I recommend setting this flag, so as to turn early branching on.
|
//
|
//
|
`define OPT_EARLY_BRANCHING
|
`define OPT_EARLY_BRANCHING
|
//
|
//
|
Line 179... |
Line 221... |
//
|
//
|
`define OPT_PIPELINED_BUS_ACCESS
|
`define OPT_PIPELINED_BUS_ACCESS
|
//
|
//
|
//
|
//
|
//
|
//
|
// OPT_SINGLE_CYCLE controls how the Zip CPU handles operations where the
|
`ifdef OPT_NEW_INSTRUCTION_SET
|
// second of two instructions uses a register output from the first of the
|
//
|
// two. If set, there will be no stalling between such a pair of instructions.
|
//
|
// If not set, the CPU will insert a stall between such a pair to give the
|
|
// result time to propagate to the second instruction. Other than the existence
|
|
// of a stall, the CPU will still yield the same results for the same
|
|
// instructions.
|
|
//
|
|
// The purpose of this is really timing: With this option defined, a logical
|
|
// or combinatorial mux is placed prior to the input of the ALU. This mux,
|
|
// together with whatever ALU operation is to take place, must both fit within
|
|
// one clock cycle. If they cannot be made to fit within the one clock cycle,
|
|
// then either the clock must be slowed down so that they can fit, or this
|
|
// flag needs to be turned off (not set) to get rid of the mux--hence speeding
|
|
// up the clock while slowing down some instructions.
|
|
//
|
//
|
`define OPT_SINGLE_CYCLE
|
// The new instruction set also defines a set of very long instruction words.
|
|
// Well, calling them "very long" instruction words is probably a misnomer,
|
|
// although we're going to do it. They're really 2x16-bit instructions---
|
|
// instruction words that pack two instructions into one word. (2x14 bit
|
|
// really--'cause you need a bit to note the instruction is a 2x instruction,
|
|
// and then 3-bits for the condition codes ...) Set OPT_VLIW to include these
|
|
// double instructions as part of the new instruction set. These allow a single
|
|
// instruction to contain two instructions within. These instructions are
|
|
// designed to get more code density from the instruction set, and to hopefully
|
|
// take some pain off of the performance of the pre-fetch and instruction cache.
|
|
//
|
|
// These new instructions, however, also necessitate a change in the Zip
|
|
// CPU--the Zip CPU can no longer execute instructions atomically. It must
|
|
// now execute non-VLIW instructions, or VLIW instruction pairs, atomically.
|
|
// This logic has been added into the ZipCPU, but it has not (yet) been
|
|
// tested thoroughly.
|
|
//
|
|
// Oh, and the assembler, the debugger, and the object file dumper, and the
|
|
// simulator all need to be updated as well ....
|
|
//
|
|
`define OPT_VLIW
|
|
//
|
|
//
|
|
`endif
|
//
|
//
|
//
|
//
|
`endif // OPT_SINGLE_FETCH
|
`endif // OPT_SINGLE_FETCH
|
//
|
//
|
//
|
//
|
|
//
|
|
// Now let's talk about peripherals for a moment. These next two defines
|
|
// control whether the DMA controller is included in the Zip System, and
|
|
// whether or not the 8 accounting timers are also included. Set these to
|
|
// include the respective peripherals, comment them out not to.
|
|
//
|
|
`define INCLUDE_DMA_CONTROLLER
|
|
`define INCLUDE_ACCOUNTING_COUNTERS
|
|
//
|
|
//
|
|
// `define DEBUG_SCOPE
|
|
`define NEW_PREFETCH_VERSION
|
|
//
|
`endif // CPUDEFS_H
|
`endif // CPUDEFS_H
|
|
|
No newline at end of file
|
No newline at end of file
|