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

Subversion Repositories marca

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/gpl.txt
0,0 → 1,340
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
 
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
Preamble
 
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
 
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
 
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
 
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
 
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
 
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
 
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
 
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
 
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
 
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
 
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
 
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
 
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
 
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
 
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
 
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
 
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
 
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
 
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
 
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
 
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
 
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
 
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
 
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
 
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
 
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
 
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
 
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
 
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
 
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
 
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
 
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
 
NO WARRANTY
 
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
 
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
 
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
 
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
 
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
 
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 
 
Also add information on how to contact you by electronic and paper mail.
 
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
 
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
 
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
 
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
 
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
 
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
 
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
/trunk/quartus/marca.pin
0,0 → 1,299
-- Copyright (C) 1991-2006 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
--
-- This is a Quartus II output file. It is for reporting purposes only, and is
-- not intended for use as a Quartus II input file. This file cannot be used
-- to make Quartus II pin assignments - for instructions on how to make pin
-- assignments, please see Quartus II help.
---------------------------------------------------------------------------------
 
 
 
---------------------------------------------------------------------------------
-- NC : No Connect. This pin has no internal connection to the device.
-- VCCINT : Dedicated power pin, which MUST be connected to VCC (1.5V).
-- VCCIO : Dedicated power pin, which MUST be connected to VCC
-- of its bank.
-- Bank 1: 3.3V
-- Bank 2: 3.3V
-- Bank 3: 3.3V
-- Bank 4: 3.3V
-- GND : Dedicated ground pin. Dedicated GND pins MUST be connected to GND.
-- It can also be used to report unused dedicated pins. The connection
-- on the board for unused dedicated pins depends on whether this will
-- be used in a future design. One example is device migration. When
-- using device migration, refer to the device pin-tables. If it is a
-- GND pin in the pin table or if it will not be used in a future design
-- for another purpose the it MUST be connected to GND. If it is an unused
-- dedicated pin, then it can be connected to a valid signal on the board
-- (low, high, or toggling) if that signal is required for a different
-- revision of the design.
-- GND+ : Unused input pin. It can also be used to report unused dual-purpose pins.
-- This pin should be connected to GND. It may also be connected to a
-- valid signal on the board (low, high, or toggling) if that signal
-- is required for a different revision of the design.
-- GND* : Unused I/O pin. This pin can either be left unconnected or
-- connected to GND. Connecting this pin to GND will improve the
-- device's immunity to noise.
-- RESERVED : Unused I/O pin, which MUST be left unconnected.
-- RESERVED_INPUT : Pin is tri-stated and should be connected to the board.
-- RESERVED_INPUT_WITH_WEAK_PULLUP : Pin is tri-stated with internal weak pull-up resistor.
-- RESERVED_INPUT_WITH_BUS_HOLD : Pin is tri-stated with bus-hold circuitry.
---------------------------------------------------------------------------------
 
Quartus II Version 6.0 Build 202 06/20/2006 Service Pack 1 SJ Web Edition
CHIP "marca" ASSIGNED TO AN: EP1C12Q240C8
 
Pin Name/Usage : Location : Dir. : I/O Standard : Voltage : I/O Bank : User Assignment
-------------------------------------------------------------------------------------------------------------
RESERVED_INPUT : 1 : : : : 1 :
RESERVED_INPUT : 2 : : : : 1 :
RESERVED_INPUT : 3 : : : : 1 :
RESERVED_INPUT : 4 : : : : 1 :
RESERVED_INPUT : 5 : : : : 1 :
RESERVED_INPUT : 6 : : : : 1 :
RESERVED_INPUT : 7 : : : : 1 :
RESERVED_INPUT : 8 : : : : 1 :
VCCIO1 : 9 : power : : 3.3V : 1 :
GND : 10 : gnd : : : :
RESERVED_INPUT : 11 : : : : 1 :
RESERVED_INPUT : 12 : : : : 1 :
RESERVED_INPUT : 13 : : : : 1 :
RESERVED_INPUT : 14 : : : : 1 :
RESERVED_INPUT : 15 : : : : 1 :
RESERVED_INPUT : 16 : : : : 1 :
RESERVED_INPUT : 17 : : : : 1 :
RESERVED_INPUT : 18 : : : : 1 :
RESERVED_INPUT : 19 : : : : 1 :
RESERVED_INPUT : 20 : : : : 1 :
RESERVED_INPUT : 21 : : : : 1 :
VCCIO1 : 22 : power : : 3.3V : 1 :
RESERVED_INPUT : 23 : : : : 1 :
~nCSO~ / RESERVED_INPUT_WITH_WEAK_PULLUP : 24 : input : LVCMOS : : 1 : N
DATA0 : 25 : input : : : 1 :
nCONFIG : 26 : : : : 1 :
VCCA_PLL1 : 27 : power : : 1.5V : :
ext_in[1] : 28 : input : LVCMOS : : 1 : Y
GND+ : 29 : : : : 1 :
GNDA_PLL1 : 30 : gnd : : : :
GNDG_PLL1 : 31 : gnd : : : :
nCEO : 32 : : : : 1 :
nCE : 33 : : : : 1 :
MSEL0 : 34 : : : : 1 :
MSEL1 : 35 : : : : 1 :
DCLK : 36 : bidir : : : 1 :
~ASDO~ / RESERVED_INPUT_WITH_WEAK_PULLUP : 37 : input : LVCMOS : : 1 : N
RESERVED_INPUT : 38 : : : : 1 :
RESERVED_INPUT : 39 : : : : 1 :
GND : 40 : gnd : : : :
RESERVED_INPUT : 41 : : : : 1 :
ext_reset : 42 : input : LVCMOS : : 1 : Y
RESERVED_INPUT : 43 : : : : 1 :
RESERVED_INPUT : 44 : : : : 1 :
RESERVED_INPUT : 45 : : : : 1 :
RESERVED_INPUT : 46 : : : : 1 :
RESERVED_INPUT : 47 : : : : 1 :
RESERVED_INPUT : 48 : : : : 1 :
RESERVED_INPUT : 49 : : : : 1 :
RESERVED_INPUT : 50 : : : : 1 :
VCCIO1 : 51 : power : : 3.3V : 1 :
GND : 52 : gnd : : : :
RESERVED_INPUT : 53 : : : : 1 :
RESERVED_INPUT : 54 : : : : 1 :
RESERVED_INPUT : 55 : : : : 1 :
RESERVED_INPUT : 56 : : : : 1 :
RESERVED_INPUT : 57 : : : : 1 :
RESERVED_INPUT : 58 : : : : 1 :
RESERVED_INPUT : 59 : : : : 1 :
RESERVED_INPUT : 60 : : : : 1 :
RESERVED_INPUT : 61 : : : : 4 :
RESERVED_INPUT : 62 : : : : 4 :
RESERVED_INPUT : 63 : : : : 4 :
RESERVED_INPUT : 64 : : : : 4 :
RESERVED_INPUT : 65 : : : : 4 :
RESERVED_INPUT : 66 : : : : 4 :
RESERVED_INPUT : 67 : : : : 4 :
RESERVED_INPUT : 68 : : : : 4 :
GND : 69 : gnd : : : :
VCCIO4 : 70 : power : : 3.3V : 4 :
GND : 71 : gnd : : : :
VCCINT : 72 : power : : 1.5V : :
RESERVED_INPUT : 73 : : : : 4 :
RESERVED_INPUT : 74 : : : : 4 :
RESERVED_INPUT : 75 : : : : 4 :
RESERVED_INPUT : 76 : : : : 4 :
RESERVED_INPUT : 77 : : : : 4 :
RESERVED_INPUT : 78 : : : : 4 :
RESERVED_INPUT : 79 : : : : 4 :
GND : 80 : gnd : : : :
VCCINT : 81 : power : : 1.5V : :
RESERVED_INPUT : 82 : : : : 4 :
RESERVED_INPUT : 83 : : : : 4 :
RESERVED_INPUT : 84 : : : : 4 :
RESERVED_INPUT : 85 : : : : 4 :
RESERVED_INPUT : 86 : : : : 4 :
RESERVED_INPUT : 87 : : : : 4 :
RESERVED_INPUT : 88 : : : : 4 :
GND : 89 : gnd : : : :
VCCINT : 90 : power : : 1.5V : :
GND : 91 : gnd : : : :
VCCIO4 : 92 : power : : 3.3V : 4 :
RESERVED_INPUT : 93 : : : : 4 :
RESERVED_INPUT : 94 : : : : 4 :
RESERVED_INPUT : 95 : : : : 4 :
GND : 96 : gnd : : : :
VCCINT : 97 : power : : 1.5V : :
RESERVED_INPUT : 98 : : : : 4 :
RESERVED_INPUT : 99 : : : : 4 :
RESERVED_INPUT : 100 : : : : 4 :
RESERVED_INPUT : 101 : : : : 4 :
GND : 102 : gnd : : : :
VCCINT : 103 : power : : 1.5V : :
RESERVED_INPUT : 104 : : : : 4 :
RESERVED_INPUT : 105 : : : : 4 :
RESERVED_INPUT : 106 : : : : 4 :
RESERVED_INPUT : 107 : : : : 4 :
RESERVED_INPUT : 108 : : : : 4 :
GND : 109 : gnd : : : :
VCCINT : 110 : power : : 1.5V : :
GND : 111 : gnd : : : :
VCCIO4 : 112 : power : : 3.3V : 4 :
RESERVED_INPUT : 113 : : : : 4 :
RESERVED_INPUT : 114 : : : : 4 :
RESERVED_INPUT : 115 : : : : 4 :
RESERVED_INPUT : 116 : : : : 4 :
RESERVED_INPUT : 117 : : : : 4 :
RESERVED_INPUT : 118 : : : : 4 :
RESERVED_INPUT : 119 : : : : 4 :
RESERVED_INPUT : 120 : : : : 4 :
RESERVED_INPUT : 121 : : : : 3 :
RESERVED_INPUT : 122 : : : : 3 :
RESERVED_INPUT : 123 : : : : 3 :
RESERVED_INPUT : 124 : : : : 3 :
RESERVED_INPUT : 125 : : : : 3 :
RESERVED_INPUT : 126 : : : : 3 :
RESERVED_INPUT : 127 : : : : 3 :
RESERVED_INPUT : 128 : : : : 3 :
GND : 129 : gnd : : : :
VCCIO3 : 130 : power : : 3.3V : 3 :
RESERVED_INPUT : 131 : : : : 3 :
RESERVED_INPUT : 132 : : : : 3 :
RESERVED_INPUT : 133 : : : : 3 :
RESERVED_INPUT : 134 : : : : 3 :
RESERVED_INPUT : 135 : : : : 3 :
RESERVED_INPUT : 136 : : : : 3 :
RESERVED_INPUT : 137 : : : : 3 :
RESERVED_INPUT : 138 : : : : 3 :
RESERVED_INPUT : 139 : : : : 3 :
RESERVED_INPUT : 140 : : : : 3 :
RESERVED_INPUT : 141 : : : : 3 :
GND : 142 : gnd : : : :
RESERVED_INPUT : 143 : : : : 3 :
RESERVED_INPUT : 144 : : : : 3 :
CONF_DONE : 145 : : : : 3 :
nSTATUS : 146 : : : : 3 :
TCK : 147 : input : : : 3 :
TMS : 148 : input : : : 3 :
TDO : 149 : output : : : 3 :
GNDG_PLL2 : 150 : gnd : : : :
GNDA_PLL2 : 151 : gnd : : : :
clock : 152 : input : LVCMOS : : 3 : Y
ext_in[0] : 153 : input : LVCMOS : : 3 : Y
VCCA_PLL2 : 154 : power : : 1.5V : :
TDI : 155 : input : : : 3 :
RESERVED_INPUT : 156 : : : : 3 :
VCCIO3 : 157 : power : : 3.3V : 3 :
RESERVED_INPUT : 158 : : : : 3 :
RESERVED_INPUT : 159 : : : : 3 :
RESERVED_INPUT : 160 : : : : 3 :
RESERVED_INPUT : 161 : : : : 3 :
RESERVED_INPUT : 162 : : : : 3 :
RESERVED_INPUT : 163 : : : : 3 :
RESERVED_INPUT : 164 : : : : 3 :
RESERVED_INPUT : 165 : : : : 3 :
RESERVED_INPUT : 166 : : : : 3 :
RESERVED_INPUT : 167 : : : : 3 :
RESERVED_INPUT : 168 : : : : 3 :
RESERVED_INPUT : 169 : : : : 3 :
RESERVED_INPUT : 170 : : : : 3 :
GND : 171 : gnd : : : :
VCCIO3 : 172 : power : : 3.3V : 3 :
RESERVED_INPUT : 173 : : : : 3 :
RESERVED_INPUT : 174 : : : : 3 :
RESERVED_INPUT : 175 : : : : 3 :
RESERVED_INPUT : 176 : : : : 3 :
ext_out[1] : 177 : output : LVCMOS : : 3 : Y
ext_out[0] : 178 : output : LVCMOS : : 3 : Y
RESERVED_INPUT : 179 : : : : 3 :
RESERVED_INPUT : 180 : : : : 3 :
RESERVED_INPUT : 181 : : : : 2 :
RESERVED_INPUT : 182 : : : : 2 :
RESERVED_INPUT : 183 : : : : 2 :
RESERVED_INPUT : 184 : : : : 2 :
RESERVED_INPUT : 185 : : : : 2 :
RESERVED_INPUT : 186 : : : : 2 :
RESERVED_INPUT : 187 : : : : 2 :
RESERVED_INPUT : 188 : : : : 2 :
VCCIO2 : 189 : power : : 3.3V : 2 :
GND : 190 : gnd : : : :
VCCINT : 191 : power : : 1.5V : :
GND : 192 : gnd : : : :
RESERVED_INPUT : 193 : : : : 2 :
RESERVED_INPUT : 194 : : : : 2 :
RESERVED_INPUT : 195 : : : : 2 :
RESERVED_INPUT : 196 : : : : 2 :
RESERVED_INPUT : 197 : : : : 2 :
VCCINT : 198 : power : : 1.5V : :
GND : 199 : gnd : : : :
RESERVED_INPUT : 200 : : : : 2 :
RESERVED_INPUT : 201 : : : : 2 :
RESERVED_INPUT : 202 : : : : 2 :
RESERVED_INPUT : 203 : : : : 2 :
VCCINT : 204 : power : : 1.5V : :
GND : 205 : gnd : : : :
RESERVED_INPUT : 206 : : : : 2 :
RESERVED_INPUT : 207 : : : : 2 :
RESERVED_INPUT : 208 : : : : 2 :
VCCIO2 : 209 : power : : 3.3V : 2 :
GND : 210 : gnd : : : :
VCCINT : 211 : power : : 1.5V : :
GND : 212 : gnd : : : :
RESERVED_INPUT : 213 : : : : 2 :
RESERVED_INPUT : 214 : : : : 2 :
RESERVED_INPUT : 215 : : : : 2 :
RESERVED_INPUT : 216 : : : : 2 :
RESERVED_INPUT : 217 : : : : 2 :
RESERVED_INPUT : 218 : : : : 2 :
RESERVED_INPUT : 219 : : : : 2 :
VCCINT : 220 : power : : 1.5V : :
GND : 221 : gnd : : : :
RESERVED_INPUT : 222 : : : : 2 :
RESERVED_INPUT : 223 : : : : 2 :
RESERVED_INPUT : 224 : : : : 2 :
RESERVED_INPUT : 225 : : : : 2 :
RESERVED_INPUT : 226 : : : : 2 :
RESERVED_INPUT : 227 : : : : 2 :
RESERVED_INPUT : 228 : : : : 2 :
VCCINT : 229 : power : : 1.5V : :
GND : 230 : gnd : : : :
VCCIO2 : 231 : power : : 3.3V : 2 :
GND : 232 : gnd : : : :
RESERVED_INPUT : 233 : : : : 2 :
RESERVED_INPUT : 234 : : : : 2 :
RESERVED_INPUT : 235 : : : : 2 :
RESERVED_INPUT : 236 : : : : 2 :
RESERVED_INPUT : 237 : : : : 2 :
RESERVED_INPUT : 238 : : : : 2 :
RESERVED_INPUT : 239 : : : : 2 :
RESERVED_INPUT : 240 : : : : 2 :
/trunk/quartus/marca.qpf
0,0 → 1,24
# Copyright (C) 1991-2006 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
 
 
 
QUARTUS_VERSION = "6.0"
DATE = "03:27:58 February 02, 2007"
 
 
# Revisions
 
PROJECT_REVISION = "marca"
PROJECT_REVISION = "speed"
/trunk/quartus/marca.qsf
0,0 → 1,166
# Copyright (C) 1991-2006 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
 
 
# The default values for assignments are stored in the file
# marca_assignment_defaults.qdf
# If this file doesn't exist, and for assignments not listed, see file
# assignment_defaults.qdf
 
# Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus II software
# and any changes you make may be lost or overwritten.
 
 
 
# Project-Wide Assignments
# ========================
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "6.0 SP1"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:01:50 OCTOBER 25, 2006"
set_global_assignment -name LAST_QUARTUS_VERSION "6.0 SP1"
set_global_assignment -name SMART_RECOMPILE ON
 
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name FAMILY Cyclone
set_global_assignment -name TOP_LEVEL_ENTITY marca
set_global_assignment -name STRATIXII_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name CYCLONE_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name STRATIX_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name MAXII_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name APEX20K_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name MERCURY_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name FLEX10K_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name IGNORE_LCELL_BUFFERS ON
set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON
set_global_assignment -name ADV_NETLIST_OPT_SYNTH_GATE_RETIME ON
set_global_assignment -name MUX_RESTRUCTURE ON
 
# Fitter Assignments
# ==================
set_global_assignment -name DEVICE EP1C12Q240C8
set_global_assignment -name FITTER_EFFORT "AUTO FIT"
set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED"
set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "AS INPUT TRI-STATED"
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON
set_global_assignment -name ROUTER_TIMING_OPTIMIZATION_LEVEL MAXIMUM
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD LVCMOS
 
# Assembler Assignments
# =====================
set_global_assignment -name RESERVE_ALL_UNUSED_PINS_NO_OUTPUT_GND "AS INPUT TRI-STATED"
 
# Simulator Assignments
# =====================
set_global_assignment -name VECTOR_INPUT_SOURCE "z:\\mnt\\wolfgang\\marca\\sim\\sim1.vwf"
set_global_assignment -name SETUP_HOLD_DETECTION ON
set_global_assignment -name SIMULATION_VDB_RESULT_FLUSH OFF
 
# -------------------
# start ENTITY(marca)
 
# end ENTITY(marca)
# -----------------
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT FAST
set_global_assignment -name FMAX_REQUIREMENT "20 MHz"
set_global_assignment -name STATE_MACHINE_PROCESSING "ONE-HOT"
set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON
set_global_assignment -name ALLOW_ANY_SHIFT_REGISTER_SIZE_FOR_RECOGNITION ON
set_global_assignment -name ENABLE_DRC_SETTINGS ON
set_global_assignment -name ENABLE_CLOCK_LATENCY ON
set_global_assignment -name ENABLE_RECOVERY_REMOVAL_ANALYSIS ON
set_global_assignment -name FMAX_REQUIREMENT "20 MHz" -section_id dspio_clock
set_global_assignment -name SIMULATION_MODE TIMING
set_global_assignment -name EDA_SIMULATION_TOOL "<None>"
set_global_assignment -name EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION OFF -section_id eda_simulation
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT NONE -section_id eda_simulation
set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS"
set_global_assignment -name GLITCH_DETECTION OFF
set_global_assignment -name AUTO_RESOURCE_SHARING ON
set_global_assignment -name REMOVE_DUPLICATE_REGISTERS ON
set_global_assignment -name REMOVE_DUPLICATE_LOGIC ON
set_global_assignment -name ALLOW_ANY_ROM_SIZE_FOR_RECOGNITION ON
set_global_assignment -name ALLOW_ANY_RAM_SIZE_FOR_RECOGNITION ON
set_global_assignment -name IGNORE_CARRY_BUFFERS ON
set_global_assignment -name IGNORE_CASCADE_BUFFERS ON
set_global_assignment -name AUTO_RAM_RECOGNITION ON
set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION ON
set_global_assignment -name AUTO_PACKED_REGISTERS_CYCLONE "MINIMIZE AREA WITH CHAINS"
set_global_assignment -name FITTER_AGGRESSIVE_ROUTABILITY_OPTIMIZATION ALWAYS
set_global_assignment -name OPTIMIZE_TIMING OFF
set_global_assignment -name OPTIMIZE_FAST_CORNER_TIMING ON
set_global_assignment -name DO_COMBINED_ANALYSIS ON
set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON
set_global_assignment -name SAVE_DISK_SPACE OFF
set_global_assignment -name OPTIMIZE_POWER_DURING_SYNTHESIS "EXTRA EFFORT"
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name MAX7000_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name VHDL_INPUT_VERSION VHDL93
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION OFF
set_location_assignment PIN_152 -to clock
set_location_assignment PIN_153 -to ext_in[0]
set_location_assignment PIN_28 -to ext_in[1]
set_location_assignment PIN_178 -to ext_out[0]
set_location_assignment PIN_177 -to ext_out[1]
set_location_assignment PIN_42 -to ext_reset
set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION AUTOMATICALLY
set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION OFF
set_global_assignment -name ROUTER_REGISTER_DUPLICATION OFF
set_global_assignment -name PLACEMENT_EFFORT_MULTIPLIER 4.0
set_global_assignment -name ROUTER_EFFORT_MULTIPLIER 1.0
set_global_assignment -name SIMULATOR_GENERATE_SIGNAL_ACTIVITY_FILE ON
set_global_assignment -name SIMULATOR_SIGNAL_ACTIVITY_FILE_OUTPUT_DESTINATION marca.saf
set_global_assignment -name POWER_USE_INPUT_FILES ON
set_global_assignment -name POWER_INPUT_FILE_NAME marca.saf -section_id marca.saf
set_global_assignment -name POWER_INPUT_FILE_TYPE SAF -section_id marca.saf
set_instance_assignment -name POWER_READ_INPUT_FILE marca.saf -to marca
set_global_assignment -name VHDL_FILE ../vhdl/marca_pkg.vhd
set_global_assignment -name VHDL_FILE ../vhdl/sc_pkg.vhd
set_global_assignment -name VHDL_FILE ../vhdl/code_memory.vhd
set_global_assignment -name VHDL_FILE ../vhdl/fetch_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/fetch.vhd
set_global_assignment -name VHDL_FILE ../vhdl/regfile_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/regfile.vhd
set_global_assignment -name VHDL_FILE ../vhdl/decode_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/decode.vhd
set_global_assignment -name VHDL_FILE ../vhdl/multiplier_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/multiplier.vhd
set_global_assignment -name VHDL_FILE ../vhdl/divider_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/divider.vhd
set_global_assignment -name VHDL_FILE ../vhdl/alu_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/alu.vhd
set_global_assignment -name VHDL_FILE ../vhdl/data_memory.vhd
set_global_assignment -name VHDL_FILE ../vhdl/data_rom.vhd
set_global_assignment -name VHDL_FILE ../vhdl/fifo.vhd
set_global_assignment -name VHDL_FILE ../vhdl/sc_uart.vhd
set_global_assignment -name VHDL_FILE ../vhdl/mem_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/mem.vhd
set_global_assignment -name VHDL_FILE ../vhdl/intr_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/intr.vhd
set_global_assignment -name VHDL_FILE ../vhdl/execute_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/execute.vhd
set_global_assignment -name VHDL_FILE ../vhdl/writeback_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/writeback.vhd
set_global_assignment -name VHDL_FILE ../vhdl/marca_ent.vhd
set_global_assignment -name VHDL_FILE ../vhdl/marca.vhd
set_global_assignment -name MIF_FILE ../vhdl/code.mif
set_global_assignment -name MIF_FILE ../vhdl/rom0.mif
set_global_assignment -name MIF_FILE ../vhdl/rom1.mif
set_global_assignment -name VECTOR_WAVEFORM_FILE ../sim/sim1.vwf
set_global_assignment -name AUTO_GLOBAL_MEMORY_CONTROLS ON
set_global_assignment -name SIMULATION_WITH_GLITCH_FILTERING_IN_NORMAL_FLOW ON
/trunk/doc/marca.dia Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
trunk/doc/marca.dia Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/doc/implementation.tex =================================================================== --- trunk/doc/implementation.tex (nonexistent) +++ trunk/doc/implementation.tex (revision 2) @@ -0,0 +1,247 @@ +\documentclass[10pt, twoside, a4paper]{article} +\usepackage{graphicx} +\usepackage{listings} + +\title{marca - McAdam's RISC Computer Architecture\\Implementation Details} +\author{Wolfgang Puffitsch} + +\begin{document} + + \maketitle + + \section{General} + + \begin{itemize} + \item 16 16-bit registers + \item 16KB instruction ROM (8192 instructions) + \item 8KB data RAM + \item 256 byte data ROM + \item 75 instructions + \item 16 interrupt vectors + \end{itemize} + + \section{Internals} + + The processor features a 4-stage pipeline: + \begin{itemize} + \item instruction fetch + \item instruction decode + \item execution/memory access + \item write back + \end{itemize} + This scheme is similar to the one used in the MIPS architecture, + only execution and write back stage are drawn together. For our + architecture does not support indexed addressing, it does not need + the ALU's result and can work in parallel, having the advantage of + reducing the possible hazards. + + Figure \ref{fig:marca} shows a rough scheme of the internals of the + processor. + \begin{figure}[ht!] + \centering + \includegraphics[width=.95\textwidth]{marca} + \caption{Internal scheme} + \label{fig:marca} + \end{figure} + + \subsection{Branches} + Branches are not predicted and if executed they stall the the + pipeline, leading to a total execution time of 4 cycles. The fetch + stage is not stalled, the decode stage however is stalled for two + cycles to compensate that. + + \subsection{Instruction fetch} + This stage is not spectacular: it simply reads an instruction from + the instruction ROM, and extracts the bits for the source and + destination registers. + + \subsection{Instruction decode} + This stage translates the bit-patterns of the opcodes to the signals + used internally for the operations. It also holds the register file + and handles access to it. Immediate values are also constructed here. + + \subsection{Execution / Memory access} + The execution stage is the heart and soul of the processor: it holds + the ALU, the memory/IO unit and a unit for interrupt handling. + + \subsubsection{ALU} + The ALU does all arithmetic and logic computations as well as taking + care of the processors flags (which are organized as seen in table + \ref{tab:flags}). + + \begin{table}[ht!] + \centering + \begin{tabular}{|p{.75em}|p{.75em}|p{.75em}|p{.75em} + |p{.75em}|p{.75em}|p{.75em}|p{.75em} + |p{.75em}|p{.75em}|p{.75em}|p{.75em} + |p{.75em}|p{.75em}|p{.75em}|p{.75em}|p{.75em}} + \multicolumn{16}{c}{Bit 15 \hfill Bit 0} \\ + \hline + & & & & & & & & & & P & I & N & V & C & Z \\ + \hline + \end{tabular} + \caption{The flag register} + \label{tab:flags} + \end{table} + + Operations which need more than one cycle to execute (multiplication, + division and modulo) block the rest of the processor until they are + finished. + + \subsubsection{Memory/IO unit} + The memory/IO unit takes care of the ordinary data memory, the data + ROM (which is mapped to the addresses right above the RAM) and the + communication to peripheral modules. Peripheral modules are located + within the memory/IO unit and mapped to the highest addresses. + + The memories (the instruction ROM too) are Altera specific; we + decided not to use generic memories, because \textsl{Quartus} can update the + contents of its proprietary ROMs without synthesizing the whole + design. Because all memories are single-ported (and thus fairly + simple) it should be easy to replace them with memories specific to + other vendors. + + We also decided against the use of external memories; larger FPGAs + can accommodate all addressable memory on-chip, so the implementation + overhead would not have paid off. + + Accesses which take more than one cycle (stores to peripheral + modules and all load operations) block the rest of the processor + until they are finished. + + \paragraph{Peripheral modules} + The peripheral modules use a slightly modified version of the SimpCon + interface. The SimpCon specific signals are pulled together to + records, and the words which can be read/written are limited to 16 + bits. For accessing such a module, one may only use \texttt{load} + and \texttt{store} instructions which point to aligned addresses. + + \paragraph{UART} + The built-in UART is derived from the sc\_uart from Martin + Sch\"oberl. Apart from adapting the SimpCon interface, an interrupt + line and two bits for enabling/masking receive (bit 3 in the status + register) and transmit (bit 2) interrupts. In the current version + address 0xFFF8 (-8) correspond to the UART's status register and + address 0xFFFA (-6) to the wr\_data/rd\_data register. + + \subsubsection{Interrupt unit} + The interrupt unit takes care of the interrupt vectors and, of + course, the triggering of interrupts. Interrupts are executed only + if the global interrupt flag is set, none of the other units is busy + and the instruction in the execution stage is valid (it takes 3 + cycles after jumps, branches etc. until a new valid instruction is + in that stage). + + Instructions which cannot be decoded as well as the ``error'' + instruction trigger interrupt 0; the ALU can trigger interrupt 1 + (division by zero), the memory unit can trigger interrupt 2 (invalid + memory access). In contrast to all other interrupts, these three + interrupts do not repeat the instruction which is executed when they + occur. + + \subsection{Write back} + The write back stage passes on the result of the execution stage to + all other stages. + + \section{Assembler} + The assembler \textsl{spar} (SPear Assembler Recycled) uses a syntax + quite like usual Unix-style assemblers. It accepts the pseudo-ops + \texttt{.file}, \texttt{.text}, \texttt{.data}, \texttt{.bss}, + \texttt{.align}, \texttt{.comm}, \texttt{.lcomm}, \texttt{.org} and + \texttt{.skip} with the usual meanings. The mnemonic \texttt{data} + initializes a byte to some constant value. In difference to the + instruction set architecture specification, \texttt{mod} and + \texttt{umod} accept three operands (if a move is needed, it is + silently inserted). + + The assembler produces three files: one file for the instruction + ROM, one file for the even bytes of the data ROM and one file for + the odd bytes of the instruction ROM. The splitting of the data is + necessary, because the data memories internally are split into two + 8-bit memories in order to support unaligned memory accesses without + delays. + + Three output formats are supported: .mif (Memory Initialization + Format), .hex (Intel Hex Format) and a binary format designed for + download via UART. + + \section{Resource usage and speed} + + The processor was synthesized with \textsl{Quartus II} for the + \textsl{Cyclone EP1C12Q240C8} FPGA with 12060 logic cells and 29952 + bytes of on-chip memory available. + + The processor needs $\sim$3550 logic cells or 29\% when being + compiled for maximum clock frequency, which is $\sim$60 MHz. When + optimizing for area, it needs $\sim$2600 logic cells or 22\% at + $\sim$25 MHz. + + The processor uses 24832 bytes or 83\% of on-chip memory. + + \section{Example} + + \subsection{Reversing a line} + + In listing \ref{lst:uart} one can see how to interface the uart via + interrupts. The program reads in a line from the UART and the writes + it back reversed. The lines 1 to 4 show how to instantiate memory + (the two bytes defined form the DOS-style end-of-line). The + lines 7 to 25 initialize the registers and register the interrupt + vectors, line 28 builds a barrier against the rest of the code. + + The lines 32 to 76 form the interrupt service routine. It first + checks if it is operating in read or in write mode. When reading, it + reads from the UART and stores the result. A mode switch occurs when + a newline character is encountered. In write mode the contents of + the buffer is written to the UART and switching back to read mode is + done when finished. + + In figure \ref{fig:sim} the results of the simulation are presented. + + \lstset{basicstyle=\footnotesize,numbers=left,numberstyle=\tiny} + \lstset{caption=Example for the UART and interrupts} + \lstset{label=lst:uart} + \lstinputlisting{uart_reverse.s} + + \begin{figure}[ht!] + \centering + \includegraphics[width=.95\textwidth]{uart_sim} + \caption{Simulation results} + \label{fig:sim} + \end{figure} + + \subsection{Computing factorials} + + The example in \ref{lst:fact} computes the factorials of 1 \ldots 9 + and writes the results to the PC via UART. Note that the last result + transmitted will be wrong, because it is truncated to 16 bits. + + \lstset{basicstyle=\footnotesize,numbers=left,numberstyle=\tiny} + \lstset{caption=Computing factorials} + \lstset{label=lst:fact} + \lstinputlisting{factorial.s} + + + \section{Versions Of This Document} + + 2006-12-14: Draft version \textbf{0.1} + + \noindent + 2006-12-29: Draft version \textbf{0.2} + \begin{itemize} + \item A few refinements. + \end{itemize} + + \noindent + 2007-01-22: Draft version \textbf{0.3} + \begin{itemize} + \item Added another example. + \end{itemize} + + \noindent + 2007-02-02: Draft version \textbf{0.4} + \begin{itemize} + \item Updated resource usage and speed section. + \end{itemize} + +\end{document} Index: trunk/doc/factorial.s =================================================================== --- trunk/doc/factorial.s (nonexistent) +++ trunk/doc/factorial.s (revision 2) @@ -0,0 +1,134 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; factorial +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; compute factorials of 1 to 9 and write results to +;;; the PC via UART +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.data + +;;; the numbers to be written are placed here +iobuf: + data 0x0A + data 0x0D + data 0 + data 0 + data 0 + data 0 + data 0 + data 0 + +;;; stack for recursive calls of factorial() +stack: + +.text +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; main() +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ldib r15, 1 ; number to start + ldib r5, 10 ; number to stop + + ldil r1, lo(stack) ; setup for factorial() + ldih r1, hi(stack) + ldil r2, lo(factorial) + ldih r2, hi(factorial) + + ldib r6, 0x30 ; setup for convert() + ldib r7, 10 + ldil r8, lo(iobuf) + ldih r8, hi(iobuf) + ldil r9, lo(convert) + ldih r9, hi(convert) + + ldib r12, -8 ; enable write interrupts + ldib r11, (1 << 2) + store r11, r12 + + ldil r12, lo(isr) ; register isr() to be called upon + ldih r12, hi(isr) ; interrupt #3 + stvec r12, 3 + + ldib r12, -6 ; address where to write data + ; to the UART + +loop: + mov r0, r15 ; r0 is the argument + call r2, r3 ; call factorial() + call r9, r3 ; call convert() + +wait: getfl r13 + btest r13, 4 ; interrupts still enabled? + brnz wait + + addi r15, 1 ; loop + cmp r15, r5 + brnz loop + +exit: br exit ; stop here after all + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; converting content of r4 to a string +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +convert: + addi r8, 2 +convert_loop: + umod r4, r7, r10 ; the conversion + add r10, r6, r10 + storel r10, r8 + addi r8, 1 + + udiv r4, r7, r4 ; next digit + + cmpi r4, 0 + brnz convert_loop + + sei ; trigger write + jmp r3 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; write out content of iobuf +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +isr: + cmpi r8, iobuf ; reached end? + brz written + + addi r8, -1 ; write data to UART + loadb r10, r8 + store r10, r12 + + reti + +written: + getshfl r10 + bclr r10, 4 ; clear interrupt flag + setshfl r10 + reti + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; recursively compute factorial +;;; argument: r0 +;;; return value: r4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +factorial: + cmpi r0, 1 ; reached end? + brule fact_leaf + + store r0, r1 ; push argument and return + addi r1, 2 ; address onto stack + store r3, r1 + addi r1, 2 + + addi r0, -1 ; call factorial(r0-1) + call r2, r3 + + addi r1, -2 ; pop argument and return + load r3, r1 ; address from stack + addi r1, -2 + load r0, r1 + + mul r0, r4, r4 ; return r0*factorial(r0-1) + jmp r3 + +fact_leaf: ; factorial(1) = 1 + ldib r4, 1 + jmp r3 Index: trunk/doc/marca.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/marca.png =================================================================== --- trunk/doc/marca.png (nonexistent) +++ trunk/doc/marca.png (revision 2)
trunk/doc/marca.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/doc/uart_sim.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/uart_sim.png =================================================================== --- trunk/doc/uart_sim.png (nonexistent) +++ trunk/doc/uart_sim.png (revision 2)
trunk/doc/uart_sim.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/doc/uart_reverse.s =================================================================== --- trunk/doc/uart_reverse.s (nonexistent) +++ trunk/doc/uart_reverse.s (revision 2) @@ -0,0 +1,79 @@ +.data + data 0x0A + data 0x0D +buffer: + +.text +;;; initialization + ldib r0, -8 ; config/status + ldib r1, -6 ; data + + ldil r2, lo(buffer) ; buffer address + ldih r2, hi(buffer) ; buffer address + + ldib r3, 0x0A ; newline character + ldib r4, 0x0D ; carriage return + + ldib r5, 0 ; mode + + ldib r7, isr ; register isr + stvec r7, 3 + + ldib r7, (1 << 3) ; enable receive interrupts + store r7, r0 + + sei ; enable interrupts + +;;; loop forever +loop: br loop + + +;;; ISR +isr: + cmpi r5, 0 ; check mode + brnz write_mode + +;;; reading +read_mode: + load r7, r1 ; read data + + cmp r7, r3 ; change mode upon newline + brnz read_CR + + ldib r7, (1 << 2) ; do the change + store r7, r0 + ldib r5, 1 + reti + +read_CR: + cmp r7, r4 ; ignore carriage return + brnz read_cont + reti + +read_cont: + storel r7, r2 ; store date + addi r2, 1 + reti + +;;; writing +write_mode: + addi r2, -1 + + cmpi r2, -1 ; change mode if there is no more data + brnz write_cont + + ldil r2, lo(buffer) ; correct pointer to buffer + ldih r2, hi(buffer) + + ldib r7, (1 << 3) ; do the change + store r7, r0 + ldib r5, 0 + reti + +write_cont: + loadl r7, r2 ; write data + store r7, r1 + reti + + + Index: trunk/doc/marca.eps =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/marca.eps =================================================================== --- trunk/doc/marca.eps (nonexistent) +++ trunk/doc/marca.eps (revision 2)
trunk/doc/marca.eps Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/doc/uart_sim.eps =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/uart_sim.eps =================================================================== --- trunk/doc/uart_sim.eps (nonexistent) +++ trunk/doc/uart_sim.eps (revision 2)
trunk/doc/uart_sim.eps Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/doc/isa.tex =================================================================== --- trunk/doc/isa.tex (nonexistent) +++ trunk/doc/isa.tex (revision 2) @@ -0,0 +1,245 @@ +\documentclass[10pt, twoside, a4paper]{article} +\usepackage{longtable} + +\newcommand{\shl}{\ensuremath{<\!\!<}} +\newcommand{\shr}{\ensuremath{>\!\!>\!\!>}} +\newcommand{\sar}{\ensuremath{>\!\!>}} +\newcommand{\at}{\ensuremath{\!\!:\!\!}} + +\title{marca - McAdam's RISC Computer Architecture\\Instruction Set Architecture} +\author{Kenan Bilic, Roland Kammerer, Wolfgang Puffitsch} + +\begin{document} + + \maketitle + + \section{General} + + \begin{itemize} + \item 16 16-bit registers, r0 \ldots r15 + \item any register as return address + \item flags: Z, C, V, N + \begin{itemize} + \item Z: all bits of the last result are zero + \item C: ``17$^{th}$ bit'' of the last result + \item N: 16$^{th}$ bit of the last result + \item V: overflow, after sub/cmp it is $r1 \at 15 \oplus r2 \at 15 + \oplus N \oplus C$, the latter two according to the result, + other operations accordingly + \item I: allow interrupts + \item P: parity of the last result + \end{itemize} + Flags are written where meaningful: P and Z are computed whenever + a register is written, arithmetic operations may change C, N and + V, interrupts clear I upon entry. + \item flags are stored and restored upon interrupt entry and exit + to/from ``shflags'' (shadow flags) + \item separate registers for interrupt vectors - read and written + through ``ldvec'' / ``stvec'' + \item Some parts come from the Alpha architecture. The handling of + branches is inspired by the Intel x86. + \item External hardware modules shall be mapped to the highest + memory locations. + \end{itemize} + + The processor uses a Harvard architecture; although it has not + prevailed in mainstream-architectures, it is still used in embedded + processors such as the Atmel AVR. The separation of code- and + data-memory is not flexible enough for mainstream systems, but with + small embedded processors the program code tends to be fixed + anyway. A Harvard architecture enables the processor to make use of + more memory (which is an issue when the address space is limited to + 64k), and the program code can be read from a ROM directly. A + transient failure thus cannot destroy the program by overwriting its + code section. + + \clearpage + + \section{Instruction Set} + + {\small + \begin{longtable}{llp{.62\textwidth}} + Instruction & Opcode & Semantics \\ + add r1, r2, r3 & \texttt{0000} & $r1 + r2 \rightarrow r3$ \\ + sub r1, r2, r3 & \texttt{0001} & $r1 - r2 \rightarrow r3$ \\ + addc r1, r2, r3 & \texttt{0010} & $r1 + r2 + C \rightarrow r3$ \\ + subc r1, r2, r3 & \texttt{0011} & $r1 - r2 - C \rightarrow r3$ \\ + and r1, r2, r3 & \texttt{0100} & $r1 \wedge r2 \rightarrow r3$ \\ + or r1, r2, r3 & \texttt{0101} & $r1 \vee r2 \rightarrow r3$ \\ + xor r1, r2, r3 & \texttt{0110} & $r1 \oplus r2 \rightarrow r3$ \\ + mul r1, r2, r3 & \texttt{0111} & $r1 * r2 \rightarrow r3$ \\ + div r1, r2, r3 & \texttt{1000} & $r1 \div r2 \rightarrow r3$ \\ + udiv r1, r2, r3 & \texttt{1001} & $r1 \div r2 \rightarrow r3, \textnormal{unsigned} $ \\ + ldil r1, n8 & \texttt{1010} & $(r1 \wedge \texttt{0xff00}) \vee n8 \rightarrow r1, -128 \leq n8 \leq 255 $ \\ + ldih r1, n8 & \texttt{1011} & $(r1 \wedge \texttt{0x00ff}) \vee (n8 \shl 8) \rightarrow r1, -128 \leq n8 \leq 255 $ \\ + ldib r1, n8 & \texttt{1100} & $n8 \rightarrow r1, -128 \leq n8 \leq 127$ \\ + \hline + mov r1, r2 & \texttt{11010000} & $r2 \rightarrow r1$ \\ + mod r1, r2 & \texttt{11010001} & $r1\ \textnormal{mod}\ r2 \rightarrow r1$ \\ + umod r1, r2 & \texttt{11010010} & $r1\ \textnormal{mod}\ r2 \rightarrow r1, \textnormal{unsigned} $ \\ + not r1, r2 & \texttt{11010011} & $\lnot r2 \rightarrow r1$ \\ + neg r1, r2 & \texttt{11010100} & $-r1 \rightarrow r2$ \\ + cmp r1, r2 & \texttt{11010101} & $r1 - r2, \textnormal{sets flags}$ \\ + addi r1, n4 & \texttt{11010110} & $r1 + n4 \rightarrow r1, -8 \leq n4 \leq 7$ \\ + cmpi r1, n4 & \texttt{11010111} & $r1 - n4, \textnormal{sets flags}, -8 \leq n4 \leq 7$ \\ + shl r1, r2 & \texttt{11011000} & $r1 \shl r2 \rightarrow r1$ \\ + shr r1, r2 & \texttt{11011001} & $r1 \shr r2 \rightarrow r1$ \\ + sar r1, r2 & \texttt{11011010} & $r1 \sar r2 \rightarrow r1$ \\ + rolc r1, r2 & \texttt{11011011} & $(r1 \shl r2) \vee (C \shl (r2-1)) \vee (r1 \shr (16-r2-1))$ \\ + rorc r1, r2 & \texttt{11011100} & $(r1 \shr r2) \vee (C \shl (16-r2)) \vee (r1 \shl (16-r2-1))$ \\ + bset r1, n4 & \texttt{11011101} & $r1 \vee (1 \shl n4) \rightarrow r1, 0 \leq n4 \leq 15$ \\ + bclr r1, n4 & \texttt{11011110} & $r1 \wedge \lnot (1 \shl n4) \rightarrow r1, 0 \leq n4 \leq 15$ \\ + btest r1, n4 & \texttt{11011111} & $(r1 \shr n4) \wedge 1 \rightarrow Z, 0 \leq n4 \leq 15$ \\ + \hline + load r1, r2 & \texttt{11100000} & $[r2] \at [r2+1] \rightarrow r1$ \\ + store r1, r2 & \texttt{11100001} & $r1 \rightarrow [r2] \at [r2+1]$ \\ + loadl r1, r2 & \texttt{11100010} & $(r1 \wedge \texttt{0xff00}) \vee [r2] \rightarrow r1$ \\ + loadh r1, r2 & \texttt{11100011} & $(r1 \wedge \texttt{0x00ff}) \vee ([r2] \shl 8) \rightarrow r1$ \\ + loadb r1, r2 & \texttt{11100100} & $[r2] \rightarrow r1, \textnormal{signed}$ \\ + storel r1, r2 & \texttt{11100101} & $(r1 \wedge \texttt{0x00ff}) \rightarrow [r2]$ \\ + storeh r1, r2 & \texttt{11100110} & $(r1 \shr 8) \rightarrow [r2]$ \\ + call r1, r2 & \texttt{11101000} & $r1 \rightarrow pc, pc \rightarrow r2$ \\ + \hline + br n8 & \texttt{11110000} & $pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brz n8 & \texttt{11110001} & $Z = 1 \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brnz n8 & \texttt{11110010} & $Z = 0 \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brle n8 & \texttt{11110011} & $(Z = 1) \vee (N \not = V) \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brlt n8 & \texttt{11110100} & $(Z = 0) \wedge (N \not = V) \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brge n8 & \texttt{11110101} & $(Z = 1) \vee (N = V) \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brgt n8 & \texttt{11110110} & $(Z = 0) \wedge (N = V) \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brule n8 & \texttt{11110111} & $(Z = 1) \vee (C = 1) \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brult n8 & \texttt{11111000} & $(Z = 0) \wedge (C = 1) \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + bruge n8 & \texttt{11111001} & $(Z = 1) \vee (C = 0) \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + brugt n8 & \texttt{11111010} & $(Z = 0) \wedge (C = 0) \Rightarrow pc + n8 \rightarrow pc, -128 \leq n8 \leq 127$ \\ + sext r1, r2 & \texttt{11111011} & $(r1 \shl 8) \sar 8 \rightarrow r2$ \\ + ldvec r1, n4 & \texttt{11111100} & $\textnormal{interrupt vector}\ n4 \rightarrow r1, 0 \leq n4 \leq 15$ \\ + stvec r1, n4 & \texttt{11111101} & $r1 \rightarrow \textnormal{interrupt vector}\ n4, 0 \leq n4 \leq 15$ \\ + \hline + jmp r1 & \texttt{111111100000} & $r1 \rightarrow pc$ \\ + jmpz r1 & \texttt{111111100001} & $Z = 1 \Rightarrow r1 \rightarrow pc$ \\ + jmpnz r1 & \texttt{111111100010} & $Z = 0 \Rightarrow r1 \rightarrow pc$ \\ + jmple r1 & \texttt{111111100011} & $(Z = 1) \vee (N \not = V) \Rightarrow r1 \rightarrow pc$ \\ + jmplt r1 & \texttt{111111100100} & $(Z = 0) \wedge (N \not = V) \Rightarrow r1 \rightarrow pc$ \\ + jmpge r1 & \texttt{111111100101} & $(Z = 1) \vee (N = V) \Rightarrow r1 \rightarrow pc$ \\ + jmpgt r1 & \texttt{111111100110} & $(Z = 0) \wedge (N = V) \Rightarrow r1 \rightarrow pc$ \\ + jmpule r1 & \texttt{111111100111} & $(Z = 1) \vee (C = 1) \Rightarrow r1 \rightarrow pc$ \\ + jmpult r1 & \texttt{111111101000} & $(Z = 0) \wedge (C = 1) \Rightarrow r1 \rightarrow pc$ \\ + jmpuge r1 & \texttt{111111101001} & $(Z = 1) \vee (C = 0) \Rightarrow r1 \rightarrow pc$ \\ + jmpugt r1 & \texttt{111111101010} & $(Z = 0) \wedge (C = 0) \Rightarrow r1 \rightarrow pc$ \\ + intr n4 & \texttt{111111101011} & $\textnormal{interrupt vector}\ n4 \rightarrow pc, pc \rightarrow ira, flags \rightarrow shflags, 0 \leq n4 \leq 15$ \\ + getira r1 & \texttt{111111101100} & $ira \rightarrow r1$ \\ + setira r1 & \texttt{111111101101} & $r1 \rightarrow ira$ \\ + getfl r1 & \texttt{111111101110} & $flags \rightarrow r1$ \\ + setfl r1 & \texttt{111111101111} & $r1 \rightarrow flags$ \\ + getshfl r1 & \texttt{111111110000} & $shflags \rightarrow r1$ \\ + setshfl r1 & \texttt{111111110001} & $r1 \rightarrow shflags$ \\ + \hline + reti & \texttt{1111111111110000} & $ira \rightarrow pc, shflags \rightarrow flags$ \\ + nop & \texttt{1111111111110001} & $\textnormal{do nothing}$ \\ + sei & \texttt{1111111111110010} & $1 \rightarrow I$ \\ + cli & \texttt{1111111111110011} & $0 \rightarrow I$ \\ + error & \texttt{1111111111111111} & $\textnormal{invalid operation}$ \\ + \end{longtable}} + + \subsection{NOTES} + \begin{itemize} + \item Apart from the standard operators, the following notation is + used in the table above: + \begin{itemize} + \item \shl, \shr, \sar are shifting operators, with semantics as in Java + \item $[x]$ means accessing memory location $x$, 8 bits wide + \item $x \at y$ means concatenating $x$ and $y$, in the sense of + forming a 16-bit value from two 8-bit values + \end{itemize} + \item Modulo does not follow the patterns for ``div'' and ``udiv'', + because there was not enough room for two more 3-operand + operations. The assembler accepts the mnemonic with 3 registers as + operands and substitute it with the according ``mov'' and ``mod'' + instructions. + \end{itemize} + + \clearpage + + \subsection{Instruction formats} + + The following formats for instructions are to be used: + + \begin{center} + \begin{tabular}{|p{1in}|p{1in}|p{1in}|p{1in}|} + \hline + Bits 15 \ldots 12 & Bits 11 \ldots 8 & Bits 7 \ldots 4 & Bits 3 \ldots 0 \\ + \hline + Opcode & r3 & r2 & r1 \\ + \hline + Opcode & \multicolumn{2}{|l|}{n8} & r1 \\ + \hline + \multicolumn{2}{|l|}{Opcode} & r2 & r1 \\ + \hline + \multicolumn{2}{|l|}{Opcode} & n4 & r1 \\ + \hline + \multicolumn{2}{|l|}{Opcode} & \multicolumn{2}{|l|}{n8} \\ + \hline + \multicolumn{3}{|l|}{Opcode} & r1 \\ + \hline + \multicolumn{3}{|l|}{Opcode} & n4 \\ + \hline + \multicolumn{4}{|l|}{Opcode} \\ + \hline + \end{tabular} + \end{center} + + \section{Versions Of This Document} + + 2006-10-04: Draft version \textbf{0.1} + + \noindent + 2006-10-05: Draft version \textbf{0.2} + \begin{itemize} + \item rearrangement of some ops + \end{itemize} + + \noindent + 2006-10-11: Draft version \textbf{0.3} + \begin{itemize} + \item replaced ``ror''/``rol'' with ``mod''/``umod'' + \item refined considerations of direction flag + \item proposal for priorities of implementation + \end{itemize} + + \noindent + 2006-10-28: Draft version \textbf{0.4} + \begin{itemize} + \item settled to singed loads + \item settled to shifts by registers + \item dropped ``push''/``pop''; the secondary result would cause a + considerable overhead + \item specified pipelining + \end{itemize} + + \noindent + 2006-10-30: Draft version \textbf{0.5} + \begin{itemize} + \item added shflags to ease interrupt (and stack) handling + \item a few refinements + \end{itemize} + + \noindent + 2006-12-02: Draft version \textbf{0.6} + \begin{itemize} + \item the first register is the target with ``mov'' and ``not'' now. + \item now the second register is always the address when accessing memory + \item reversed order with immediate loads + \item ``ldvec'' and ``stvec'' use the same order now + \item fixed instruction format for immediate loads + \end{itemize} + + \noindent + 2006-12-14: Draft version \textbf{0.7} + \begin{itemize} + \item dropped ``ldpgm'' in favor of a ROM which is mapped to the + ordinary memory space + \item moved section about pipelinign to the implementation document + \item removed note about interrupts; they are implemented already + \end{itemize} + +\end{document} Index: trunk/doc/Makefile =================================================================== --- trunk/doc/Makefile (nonexistent) +++ trunk/doc/Makefile (revision 2) @@ -0,0 +1,19 @@ +all: isa.ps.gz isa.pdf implementation.ps.gz implementation.pdf + +EXTERN_DATA: factorial.s uart_reverse.s marca.eps marca.png uart_sim.eps uart_sim.png + +%.dvi: %.tex $(EXTERN_DATA) + latex $< + latex $< + +%.ps: %.dvi + dvips $< -o $@ + +%.ps.gz: %.ps + gzip -c < $< > $@ + +%.pdf: %.tex %.dvi + pdflatex $< + +clean: + rm -f *.ps *.pdf *.dvi *.aux *.log \ No newline at end of file Index: trunk/spar/emit.c =================================================================== --- trunk/spar/emit.c (nonexistent) +++ trunk/spar/emit.c (revision 2) @@ -0,0 +1,232 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include + +#include +#include + +#include "spar.h" +#include "optab.h" +#include "code.h" +#include "emit.h" +#include "exprs.h" +#include "segtab.h" + +void emit_op(struct seg *seg, struct op op) +{ + adjust_segsize(seg, seg->pos+1); + seg->code[seg->pos] = op; + seg->pos++; +} + +void emit_nop(struct seg *seg) +{ + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, NOP); + + trace_listing(seg, seg->pos, "nop"); + + seg->pos++; +} + +void emit_zero(struct seg *seg) +{ + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, DATA); + set_expr(seg, seg->pos, 0, "0"); + set_mode(seg, seg->pos, 0, 'n'); + + trace_listing(seg, seg->pos, "data 0"); + + seg->pos++; +} + +void emit_data(struct seg *seg, char *expr) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, DATA); + set_expr(seg, seg->pos, 0, expr); + set_mode(seg, seg->pos, 0, 'n'); + + snprintf(buf, CODE_MAX_LISTLEN, "data\t%s", expr); + trace_listing(seg, seg->pos, buf); + + seg->pos++; + + free(buf); +} + +void emit_ldil(struct seg *seg, uint16_t reg, char *expr) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, LDIL); + set_regnum(seg, seg->pos, 0, reg); + set_mode(seg, seg->pos, 0, 'r'); + set_expr(seg, seg->pos, 1, expr); + set_mode(seg, seg->pos, 1, 'n'); + + snprintf(buf, CODE_MAX_LISTLEN, "ldil\tr%d, %s", reg, expr); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} + +void emit_ldih(struct seg *seg, uint16_t reg, char *expr) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, LDIH); + set_regnum(seg, seg->pos, 0, reg); + set_mode(seg, seg->pos, 0, 'r'); + set_expr(seg, seg->pos, 1, expr); + set_mode(seg, seg->pos, 2, 'n'); + + snprintf(buf, CODE_MAX_LISTLEN, "ldih\tr%d, %s", reg, expr); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} + +void emit_ldib(struct seg *seg, uint16_t reg, char *expr) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, LDIB); + set_regnum(seg, seg->pos, 0, reg); + set_mode(seg, seg->pos, 0, 'r'); + set_expr(seg, seg->pos, 1, expr); + set_mode(seg, seg->pos, 1, 'n'); + + snprintf(buf, CODE_MAX_LISTLEN, "ldib\tr%d, %s", reg, expr); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} + +void emit_addi(struct seg *seg, uint16_t reg, char *expr) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, ADDI); + set_regnum(seg, seg->pos, 0, reg); + set_mode(seg, seg->pos, 0, 'r'); + set_expr(seg, seg->pos, 1, expr); + set_mode(seg, seg->pos, 1, 'n'); + + snprintf(buf, CODE_MAX_LISTLEN, "addi\tr%d, %s", reg, expr); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} + +void emit_cmp(struct seg *seg, uint16_t reg1, uint16_t reg2) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, CMP); + set_regnum(seg, seg->pos, 0, reg1); + set_mode(seg, seg->pos, 0, 'r'); + set_regnum(seg, seg->pos, 1, reg2); + set_mode(seg, seg->pos, 1, 'r'); + + snprintf(buf, CODE_MAX_LISTLEN, "cmp\tr%d, r%d", reg1, reg2); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} + +void emit_load(struct seg *seg, uint16_t reg1, uint16_t reg2) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, LOAD); + set_regnum(seg, seg->pos, 0, reg1); + set_mode(seg, seg->pos, 0, 'r'); + set_regnum(seg, seg->pos, 1, reg2); + set_mode(seg, seg->pos, 1, 'r'); + + snprintf(buf, CODE_MAX_LISTLEN, "load\tr%d, r%d", reg1, reg2); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} + +void emit_store(struct seg *seg, uint16_t reg1, uint16_t reg2) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, STORE); + set_regnum(seg, seg->pos, 0, reg1); + set_mode(seg, seg->pos, 0, 'r'); + set_regnum(seg, seg->pos, 1, reg2); + set_mode(seg, seg->pos, 1, 'r'); + + snprintf(buf, CODE_MAX_LISTLEN, "store\tr%d, r%d", reg1, reg2); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} + +void emit_jmp(struct seg *seg, uint16_t reg) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, JMP); + set_regnum(seg, seg->pos, 0, reg); + set_mode(seg, seg->pos, 0, 'r'); + + snprintf(buf, CODE_MAX_LISTLEN, "jmp\tr%d", reg); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} + +void emit_brnz(struct seg *seg, char *expr) +{ + char *buf = xmalloc(CODE_MAX_LISTLEN); + + adjust_segsize(seg, seg->pos+1); + set_op(seg, seg->pos, BRNZ); + set_expr(seg, seg->pos, 0, expr); + set_mode(seg, seg->pos, 0, 'a'); + + snprintf(buf, CODE_MAX_LISTLEN, "brnz\t%s", expr); + trace_listing(seg, seg->pos, buf); + seg->pos++; + + free(buf); +} Index: trunk/spar/test.s =================================================================== --- trunk/spar/test.s (nonexistent) +++ trunk/spar/test.s (revision 2) @@ -0,0 +1,11 @@ +.data +data 0xaa +data 0x55 +data 0x12 +data 0x34 +.text +add r1, r2, r3 +.bss +data 0 +data 0 +data 0 \ No newline at end of file Index: trunk/spar/symtab.c =================================================================== --- trunk/spar/symtab.c (nonexistent) +++ trunk/spar/symtab.c (revision 2) @@ -0,0 +1,119 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include +#include +#include +#include + +#include "spar.h" +#include "symtab.h" + +static struct sym_info *symtab[SYMTAB_SIZE]; + +uint32_t hash_string (const char *str) +{ + uint32_t hash; + const char *ptr = str; + size_t len = strlen(str); + for (hash = 0; len; len--, ptr++) + { + hash = 31 * hash + *ptr; + } + return hash; +} + +char *trim_string (char *str) +{ + while ((str[0] == ' ') || (str[0] == '\t')) + { + str++; + } + while ((str[strlen(str)-1] == ' ') + || (str[strlen(str)-1] == '\t')) + { + str[strlen(str)-1] = '\0'; + } + return str; +} + +char *localize_string (char *str) +{ + if (str[0] == '.') + { + char *buf = xmalloc(strlen(str)+10); + sprintf(buf, "%s@%08lx", str, file_count); + return buf; + } + return str; +} + +void init_symtab(void) +{ + int i; + for (i = 0; i < SYMTAB_SIZE; i++) + { + symtab[i] = NULL; + } +} + +void push_sym(const char *symbol, uint8_t type, uint32_t addr) +{ + uint32_t pos; + struct sym_info *sym; + + pos = hash_string(symbol) % SYMTAB_SIZE; + sym = xmalloc(sizeof(struct sym_info)); + sym->symbol = symbol; + sym->type = type; + sym->addr = addr; + sym->next = symtab[pos]; + symtab[pos] = sym; +} + +struct sym_info *get_sym(const char *symbol) +{ + uint32_t pos; + struct sym_info *sym; + + pos = hash_string(symbol) % SYMTAB_SIZE; + sym = symtab[pos]; + + while ((sym != NULL) && (strcmp(sym->symbol, symbol) != 0)) + { + sym = sym->next; + } + + return sym; +} + +void reloc_syms(uint8_t type, uint32_t offset) +{ + uint32_t pos; + struct sym_info *sym; + + for (pos = 0; pos < SYMTAB_SIZE; pos++) + { + for (sym = symtab[pos]; sym != NULL; sym = sym->next) + { + if (sym->type == type) + { + sym->addr += offset; + } + } + } +} Index: trunk/spar/output.c =================================================================== --- trunk/spar/output.c (nonexistent) +++ trunk/spar/output.c (revision 2) @@ -0,0 +1,224 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include +#include +#include + +#include "spar.h" +#include "ui.h" +#include "output.h" +#include "segtab.h" +#include "code.h" + +char *itob(uint32_t val, uint8_t width) +{ + char *retval = xmalloc(width+1); + retval[width] = '\0'; + while (width-- > 0) + { + retval[width] = (val & 1) ? '1' : '0'; + val >>= 1; + } + return retval; +} + +void print_download(FILE *f, FILE *r0, FILE *r1) +{ + struct seg *seg = get_current_seg(); + uint32_t pos; + + if (!nostart) + { + fprintf(f, "%c%c", 'U', '\n'); + } + for (pos = 0; pos < seg->pos; pos++) + { + uint16_t data = get_code(seg, pos); + fprintf(f, "%c%c%c%c%c%c", + (uint8_t)((pos >> 8) & 0xFF), + (uint8_t)(pos & 0xFF), + 0, + (uint8_t)((data >> 8) & 0xFF), + (uint8_t)(data & 0xFF), + '\n'); + } + for ( ; pos < codesize; pos++) + { + fprintf(f, "%c%c%c%c%c%c", + (uint8_t)((pos >> 8) & 0xFF), + (uint8_t)(pos & 0xFF), + 0, + (uint8_t)((filler >> 8) & 0xFF), + (uint8_t)(filler & 0xFF), + '\n'); + } + if (!noend) + { + fprintf(f, "%c%c%c", 0x55, 0xFF, 1); + } +} + +void print_intel(FILE *f, FILE *r0, FILE *r1) +{ + struct seg *seg; + uint32_t pos; + + /* instructions */ + seg = get_seg(SEG_PILE); + for (pos = 0; pos < seg->pos; pos++) + { + uint16_t data = get_code(seg, pos); + uint8_t chksum = -(2 + ((pos >> 8) & 0xFF) + (pos & 0xFF) + + ((data >> 8) & 0xFF) + (data & 0xFF)); + fprintf(f, ":%02x%04x%02x%04x%02x%c", + 2, (uint16_t)pos, 0, data, chksum, '\n'); + } + for ( ; pos < codesize; pos++) + { + uint8_t chksum = -(2 + ((pos >> 8) & 0xFF) + (pos & 0xFF) + + ((filler >> 8) & 0xFF) + (filler & 0xFF)); + fprintf(f, ":%02x%04x%02x%04x%02x%c", + 2, (uint16_t)pos, 0, filler, chksum, '\n'); + } + fprintf(f, ":00000001ff\n"); + + /* even ROM adresses */ + seg = get_seg(SEG_DATA); + for (pos = 0; pos < seg->pos; pos+=2) + { + uint16_t data = get_code(seg, pos); + uint8_t chksum = -(1 + ((pos/2 >> 8) & 0xFF) + (pos/2 & 0xFF) + + (data & 0xFF)); + fprintf(r0, ":%02x%04x%02x%02x%02x%c", + 1, (uint16_t)pos/2, 0, data & 0xFF, chksum, '\n'); + } + for ( ; pos < romsize; pos+=2) + { + uint8_t chksum = -(1 + ((pos/2 >> 8) & 0xFF) + (pos/2 & 0xFF) + + (filler & 0xFF)); + fprintf(r0, ":%02x%04x%02x%02x%02x%c", + 1, (uint16_t)pos/2, 0, filler & 0xFF, chksum, '\n'); + } + fprintf(r0, ":00000001ff\n"); + + /* odd ROM adresses */ + seg = get_seg(SEG_DATA); + for (pos = 1; pos < seg->pos; pos+=2) + { + uint16_t data = get_code(seg, pos); + uint8_t chksum = -(1 + ((pos/2 >> 8) & 0xFF) + (pos/2 & 0xFF) + + (data & 0xFF)); + fprintf(r1, ":%02x%04x%02x%02x%02x%c", + 1, (uint16_t)pos/2, 0, data & 0xFF, chksum, '\n'); + } + for ( ; pos < romsize; pos+=2) + { + uint8_t chksum = -(1 + ((pos/2 >> 8) & 0xFF) + (pos/2 & 0xFF) + + ((filler >> 8) & 0xFF) + (filler & 0xFF)); + fprintf(r1, ":%02x%04x%02x%02x%02x%c", + 1, (uint16_t)pos/2, 0, filler & 0xFF, chksum, '\n'); + } + fprintf(r1, ":00000001ff\n"); +} + +void print_mif(FILE *f, FILE *r0, FILE *r1) +{ + struct seg *seg; + uint32_t pos; + + /* instructions */ + seg = get_seg(SEG_PILE); + + fprintf(f, "DEPTH=%lu;\n", codesize); + fprintf(f, "WIDTH=16;\n"); + fprintf(f, "ADDRESS_RADIX=HEX;\n"); + fprintf(f, "DATA_RADIX=BIN;\n\n"); + fprintf(f, "CONTENT\nBEGIN\n\n"); + + fprintf(f, "%% Assembly output\t%%\n"); + + for (pos = 0; pos < seg->pos; pos++) + { + uint16_t data = get_code(seg, pos); + fprintf(f, "%4x:\t%s;\t%% %s\t%%\n", (uint16_t)pos, + itob(data, 16), get_listing(seg, pos)); + } + + if (seg->pos < codesize) + { + fprintf(f, "\n[%4x..%4x]:\t%s;\t%% Filler\t%%\n", + (uint16_t)seg->pos, (uint16_t)(codesize-1), + itob(filler, 16)); + } + + fprintf(f, "\nEND;\n"); + + /* even ROM addresses */ + seg = get_seg(SEG_DATA); + + fprintf(r0, "DEPTH=%lu;\n", romsize/2); + fprintf(r0, "WIDTH=8;\n"); + fprintf(r0, "ADDRESS_RADIX=HEX;\n"); + fprintf(r0, "DATA_RADIX=BIN;\n\n"); + fprintf(r0, "CONTENT\nBEGIN\n\n"); + + fprintf(r0, "%% Assembly output\t%%\n"); + + for (pos = 0; pos < seg->pos; pos += 2) + { + uint16_t data = get_code(seg, pos); + fprintf(r0, "%4x:\t%s;\t%% %s\t%%\n", (uint16_t)pos/2, + itob(data, 8), get_listing(seg, pos)); + } + + if (seg->pos < romsize) + { + fprintf(r0, "\n[%4x..%4x]:\t%s;\t%% Filler\t%%\n", + (uint16_t)seg->pos/2, (uint16_t)(romsize/2-1), + itob(filler, 8)); + } + + fprintf(r0, "\nEND;\n"); + + /* odd ROM addresses */ + seg = get_seg(SEG_DATA); + + fprintf(r1, "DEPTH=%lu;\n", romsize/2); + fprintf(r1, "WIDTH=8;\n"); + fprintf(r1, "ADDRESS_RADIX=HEX;\n"); + fprintf(r1, "DATA_RADIX=BIN;\n\n"); + fprintf(r1, "CONTENT\nBEGIN\n\n"); + + fprintf(r1, "%% Assembly output\t%%\n"); + + for (pos = 1; pos < seg->pos; pos += 2) + { + uint16_t data = get_code(seg, pos); + fprintf(r1, "%4x:\t%s;\t%% %s\t%%\n", (uint16_t)pos/2, + itob(data, 8), get_listing(seg, pos)); + } + + if (seg->pos < romsize) + { + fprintf(r1, "\n[%4x..%4x]:\t%s;\t%% Filler\t%%\n", + (uint16_t)seg->pos/2, (uint16_t)(romsize/2-1), + itob(filler, 8)); + } + + fprintf(r1, "\nEND;\n"); +} Index: trunk/spar/checks.c =================================================================== --- trunk/spar/checks.c (nonexistent) +++ trunk/spar/checks.c (revision 2) @@ -0,0 +1,229 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include +#include + +#include "spar.h" +#include "ui.h" +#include "checks.h" +#include "code.h" +#include "exprs.h" +#include "optab.h" +#include "segtab.h" +#include "symtab.h" + +int check_premature(void) +{ + if (args_to_match > 0) + { + fprintf(stderr, "not enough valid items in line %lu\n", line_count); + error_count++; + return 1; + } + return 0; +} + +int check_arg_count(void) +{ + if (args_to_match == 0) + { + fprintf(stderr, "too many items in line %lu\n", line_count); + error_count++; + return 1; + } + else if (args_to_match == -1) + { + fprintf(stderr, "no valid mnemonic in line %lu\n", line_count); + args_to_match = -2; + error_count++; + return 1; + } + else if ((args_to_match & 1) == 0) + { + fprintf(stderr, "missing colon in line %lu\n", line_count); + error_count++; + return 1; + } + + return 0; +} + +int check_org_advances(struct seg *seg, uint32_t org) +{ + if (seg->pos > org) + { + fprintf(stderr, "trying to move .org backwards in line %lu\n", line_count); + error_count++; + return 1; + } + return 0; +} + +int check_colon_ok(void) +{ + if ((args_to_match & 1) != 0) + { + fprintf(stderr, "superfluous colon in line %lu\n", line_count); + error_count++; + return 1; + } + + return 0; +} + +int check_arg_type(struct seg* seg, uint32_t pos, uint8_t index, char type) +{ + if (((type == 'r') + && (get_arg_type(seg, pos, index) != 'r')) + || ((type == 'n') + && (get_arg_type(seg, pos, index) != 'n') + && (get_arg_type(seg, pos, index) != 'a'))) + + { + fprintf(stderr, "wrong argtype `%c' in line %lu\n", type, line_count); + error_count++; + return 1; + } + return 0; +} + +int check_sym_dup(const char *s) +{ + if (get_sym(s) != NULL) + { + fprintf(stderr, "duplicate symbol `%s' in line %lu\n", s, line_count); + error_count++; + return 1; + } + return 0; +} + +int check_code_size(void) +{ + if (get_seg(SEG_TEXT)->pos > codesize) + { + fprintf(stderr, + "code (%lu instrucions) is too large for instruction ROM (%lu instructions)\n", + get_seg(SEG_TEXT)->pos, codesize); + error_count++; + return 1; + } + return 0; +} + +int check_data_size(void) +{ + if (output_mode == MODE_DOWNLOAD + && get_seg(SEG_DATA)->pos > 0) + { + fprintf(stderr, + "initialized data (%lu words) not supported for download format\n", + get_seg(SEG_DATA)->pos, romsize); + error_count++; + return 1; + } + + if (get_seg(SEG_DATA)->pos > romsize) + { + fprintf(stderr, + "initialized data (%lu words) is too large for data ROM (%lu words)\n", + get_seg(SEG_DATA)->pos, romsize); + error_count++; + return 1; + } + + if ((get_seg(SEG_DATA)->pos+get_seg(SEG_BSS)->pos) > datasize) + { + fprintf(stderr, + "data (%lu words) is too large for RAM (%lu words)\n", + (get_seg(SEG_DATA)->pos+get_seg(SEG_BSS)->pos), datasize); + error_count++; + return 1; + } + return 0; +} + +int check_mnemonic(struct seg* seg, uint32_t pos) +{ + if (0) + { + fprintf(stderr, "mnemonic reserved, but not supported\n"); + error_count++; + return 1; + } + return 0; +} + +int check_ranges(struct seg* seg, uint32_t pos) +{ + uint8_t count = get_arg_count(seg, pos); + uint8_t index; + int retval = 0; + + for (index = 0; index < count; index++) + { + switch (get_arg_type(seg, pos, index)) + { + case 'r': + if ((get_regnum(seg, pos, index) < get_arg_min(seg, pos, index)) + || (get_regnum(seg, pos, index) > get_arg_max(seg, pos, index))) + { + fprintf(stderr, "invalid register: r%d\n", get_regnum(seg, pos, index)); + error_count++; + retval = 1; + } + break; + case 'n': + if (get_expr(seg, pos, index) == NULL) + { + fprintf(stderr, "missing expression, probably confused by prior errors\n"); + error_count++; + retval = 1; + } + else if ((expr_evaluate(get_expr(seg, pos, index)) < get_arg_min(seg, pos, index)) + || (expr_evaluate(get_expr(seg, pos, index)) > get_arg_max(seg, pos, index))) + { + fprintf(stderr, "number out of range [%ld..%ld]: %lld\n", + get_arg_min(seg, pos, index), get_arg_max(seg, pos, index), + expr_evaluate(get_expr(seg, pos, index))); + error_count++; + retval = 1; + } + break; + case 'a': + if ((expr_evaluate(get_expr(seg, pos, index)) < get_arg_min(seg, pos, index)) + || (expr_evaluate(get_expr(seg, pos, index)) > get_arg_max(seg, pos, index))) + { + fprintf(stderr, "relative address out of range [%ld..%ld]: %lld\n", + get_arg_min(seg, pos, index), get_arg_max(seg, pos, index), + expr_evaluate(get_expr(seg, pos, index))); + error_count++; + retval = 1; + } + break; + default: + fprintf(stderr, "invalid operand constraint: %c\n", + get_arg_type(seg, pos, index)); + error_count++; + retval = 1; + } + } + + return retval; +} + Index: trunk/spar/emit.h =================================================================== --- trunk/spar/emit.h (nonexistent) +++ trunk/spar/emit.h (revision 2) @@ -0,0 +1,43 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _EMIT_H_ +#define _EMIT_H_ + +#include + +#include "segtab.h" + +void emit_op(struct seg*, struct op); + +void emit_nop(struct seg *); +void emit_zero(struct seg *); + +void emit_data(struct seg *, char *); + +void emit_ldil(struct seg *, uint16_t, char *); +void emit_ldih(struct seg *, uint16_t, char *); +void emit_ldib(struct seg *, uint16_t, char *); +void emit_load(struct seg *, uint16_t, uint16_t); +void emit_store(struct seg *, uint16_t, uint16_t); +void emit_cmp(struct seg *, uint16_t, uint16_t); +void emit_addi(struct seg *, uint16_t, char*); +void emit_jmp(struct seg *, uint16_t); +void emit_brnz(struct seg *, char*); + + +#endif /* _EMIT_H_ */ Index: trunk/spar/symtab.h =================================================================== --- trunk/spar/symtab.h (nonexistent) +++ trunk/spar/symtab.h (revision 2) @@ -0,0 +1,43 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _SYMTAB_H_ +#define _SYMTAB_H_ + +#include + +#define SYMTAB_SIZE 4096 + +uint32_t hash_string (const char *); +char *trim_string (char *); +char *localize_string (char *); + +struct sym_info +{ + const char *symbol; + uint8_t type; + uint32_t addr; + struct sym_info *next; +}; + +void init_symtab(void); + +void push_sym(const char *, uint8_t, uint32_t); +struct sym_info *get_sym(const char *); +void reloc_syms(uint8_t type, uint32_t offset); + +#endif /* _SYMTAB_H_ */ Index: trunk/spar/segtab.c =================================================================== --- trunk/spar/segtab.c (nonexistent) +++ trunk/spar/segtab.c (revision 2) @@ -0,0 +1,74 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include + +#include +#include + +#include "spar.h" +#include "segtab.h" + +static struct seg segtab[4]; +static uint8_t current_segnum; + +void init_seg(uint8_t segnum, uint32_t size) +{ + int i; + + segtab[segnum].max = size; + segtab[segnum].code = xmalloc(segtab[segnum].max*sizeof(struct op)); + + for (i = 0; i < segtab[segnum].max; i++) + set_listing(&segtab[segnum], i, ""); +} + +void set_current_segnum(uint8_t segnum) +{ + current_segnum = segnum; +} + +uint8_t get_current_segnum(void) +{ + return current_segnum; +} + +struct seg *get_current_seg(void) +{ + return &segtab[current_segnum]; +} + +struct seg *get_seg(uint8_t segnum) +{ + return &segtab[segnum]; +} + +void adjust_segsize(struct seg *seg, uint32_t size) +{ + if (size >= seg->max-1) + { + uint32_t i; + + seg->code = xrealloc(seg->code, 2*seg->max*sizeof(struct op)); + for (i = seg->max; i < 2*seg->max; i++) + { + set_listing(seg, i, ""); + } + seg->max *= 2; + } +} + Index: trunk/spar/output.h =================================================================== --- trunk/spar/output.h (nonexistent) +++ trunk/spar/output.h (revision 2) @@ -0,0 +1,29 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _OUTPUT_H_ +#define _OUTPUT_H_ + +#include +#include + +char *itob(uint32_t, uint8_t); +void print_download(FILE *, FILE *, FILE *); +void print_intel(FILE *, FILE *, FILE *); +void print_mif(FILE *, FILE *, FILE *); + +#endif /* _OUTPUT_H_ */ Index: trunk/spar/checks.h =================================================================== --- trunk/spar/checks.h (nonexistent) +++ trunk/spar/checks.h (revision 2) @@ -0,0 +1,36 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _CHECKS_H_ +#define _CHECKS_H_ + +#include + +#include "segtab.h" + +int check_premature(void); +int check_arg_count(void); +int check_arg_type(struct seg *, uint32_t, uint8_t, char); +int check_org_advances(struct seg *, uint32_t); +int check_colon_ok(void); +int check_sym_dup(const char *s); +int check_code_size(void); +int check_data_size(void); +int check_mnemonic(struct seg *, uint32_t); +int check_ranges(struct seg *, uint32_t); + +#endif /* _CHECKS_H_ */ Index: trunk/spar/optab.c =================================================================== --- trunk/spar/optab.c (nonexistent) +++ trunk/spar/optab.c (revision 2) @@ -0,0 +1,221 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include + +#include "optab.h" +#include "segtab.h" + +const struct op_info optab [] = { + +/* #define DATA 0 */ + { 0x0000, 1, { { 'n', 8, 0, -0x80, 0xFF } } }, + +/* #define ADD 1 */ + { 0x0000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define SUB 2 */ + { 0x1000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define ADDC 3 */ + { 0x2000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define SUBC 4 */ + { 0x3000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define AND 5 */ + { 0x4000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define OR 6 */ + { 0x5000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define XOR 7 */ + { 0x6000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define MUL 8 */ + { 0x7000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define DIV 9 */ + { 0x8000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define UDIV 10 */ + { 0x9000, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 8, 0, 15 } } }, +/* #define LDIL 11 */ + { 0xA000, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 8, 4, -128, 255 } } }, +/* #define LDIH 12 */ + { 0xB000, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 8, 4, -128, 255 } } }, +/* #define LDIB 13 */ + { 0xC000, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 8, 4, -128, 128 } } }, + +/* #define MOV 14 */ + { 0xD000, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, + + /* mod an umod are a bit of a kludge and need separate unfolding, + they are 2-operand instructions really */ +/* #define MOD 15 */ + { 0xD100, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 16, 0, 15 } } }, +/* #define UMOD 16 */ + { 0xD200, 3, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 }, { 'r', 4, 16, 0, 15 } } }, + +/* #define NOT 17 */ + { 0xD300, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define NEG 18 */ + { 0xD400, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define CMP 19 */ + { 0xD500, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define ADDI 20 */ + { 0xD600, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 4, 4, -8, 7 } } }, +/* #define CMPI 21 */ + { 0xD700, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 4, 4, -8, 7 } } }, +/* #define SHL 22 */ + { 0xD800, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define SHR 23 */ + { 0xD900, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define SAR 24 */ + { 0xDA00, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define ROLC 25 */ + { 0xDB00, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define RORC 26 */ + { 0xDC00, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define BSET 27 */ + { 0xDD00, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 4, 4, 0, 15 } } }, +/* #define BCLR 28 */ + { 0xDE00, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 4, 4, 0, 15 } } }, +/* #define BTEST 29 */ + { 0xDF00, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 4, 4, 0, 15 } } }, + +/* #define LOAD 30 */ + { 0xE000, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define STORE 31 */ + { 0xE100, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define LOADL 32 */ + { 0xE200, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define LOADH 33 */ + { 0xE300, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define LOADB 34 */ + { 0xE400, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define STOREL 35 */ + { 0xE500, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define STOREH 36 */ + { 0xE600, 2, { { 'r', 4, 0, 0, 15 }, { 'r', 4, 4, 0, 15 } } }, +/* #define CALL 37 */ + { 0xE800, 2, { { 'r', 4, 4, 0, 15 }, { 'r', 4, 0, 0, 15 } } }, + +/* #define BR 38 */ + { 0xF000, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRZ 39 */ + { 0xF100, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRNZ 40 */ + { 0xF200, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRLE 41 */ + { 0xF300, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRLT 42 */ + { 0xF400, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRGE 43 */ + { 0xF500, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRGT 44 */ + { 0xF600, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRULE 45 */ + { 0xF700, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRULT 46 */ + { 0xF800, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRUGE 47 */ + { 0xF900, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define BRUGT 48 */ + { 0xFA00, 1, { { 'a', 8, 0, -128, 127 } } }, +/* #define SEXT 49 */ + { 0xFB00, 2, { { 'r', 4, 4, 0, 15 }, { 'r', 4, 0, 0, 15 } } }, +/* #define LDVEC 50 */ + { 0xFC00, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 4, 4, 0, 15 } } }, +/* #define STVEC 51 */ + { 0xFD00, 2, { { 'r', 4, 0, 0, 15 }, { 'n', 4, 4, 0, 15 } } }, + +/* #define JMP 52 */ + { 0xFE00, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPZ 53 */ + { 0xFE10, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPNZ 54 */ + { 0xFE20, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPLE 55 */ + { 0xFE30, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPLT 56 */ + { 0xFE40, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPGE 57 */ + { 0xFE50, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPGT 58 */ + { 0xFE60, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPULE 59 */ + { 0xFE70, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPULT 60 */ + { 0xFE80, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPUGE 61 */ + { 0xFE90, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define JMPUGT 62 */ + { 0xFEA0, 1, { { 'r', 4, 0, 0, 15 } } }, + +/* #define INTR 63 */ + { 0xFEB0, 1, { { 'n', 4, 0, 0, 15 } } }, +/* #define GETIRA 64 */ + { 0xFEC0, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define SETIRA 65 */ + { 0xFED0, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define GETFL 66 */ + { 0xFEE0, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define SETFL 67 */ + { 0xFEF0, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define GETSHFL 68 */ + { 0xFF00, 1, { { 'r', 4, 0, 0, 15 } } }, +/* #define SETSHFL 69 */ + { 0xFF10, 1, { { 'r', 4, 0, 0, 15 } } }, + +/* #define RETI 70 */ + { 0xFFF0, 0 }, +/* #define NOP 71 */ + { 0xFFF1, 0 }, +/* #define SEI 72 */ + { 0xFFF2, 0 }, +/* #define CLI 73 */ + { 0xFFF3, 0 }, +/* #define ERROR 74 */ + { 0xFFFF, 0 }, + +/* #define ALIGN 75 */ + { 0x0000 } +}; + +uint16_t get_op_code(struct seg *seg, uint32_t pos) +{ + return optab[seg->code[pos].op].opcode; +} + +int8_t get_arg_count(struct seg *seg, uint32_t pos) +{ + return optab[seg->code[pos].op].argc; +} + +char get_arg_type(struct seg *seg, uint32_t pos, uint8_t index) +{ + return optab[seg->code[pos].op].argv[index].type; +} + +uint8_t get_arg_width(struct seg *seg, uint32_t pos, uint8_t index) +{ + return optab[seg->code[pos].op].argv[index].width; +} +uint8_t get_arg_offset(struct seg *seg, uint32_t pos, uint8_t index) +{ + return optab[seg->code[pos].op].argv[index].offset; +} +int32_t get_arg_min(struct seg *seg, uint32_t pos, uint8_t index) +{ + return optab[seg->code[pos].op].argv[index].min; +} +int32_t get_arg_max(struct seg *seg, uint32_t pos, uint8_t index) +{ + return optab[seg->code[pos].op].argv[index].max; +} Index: trunk/spar/exprs.h =================================================================== --- trunk/spar/exprs.h (nonexistent) +++ trunk/spar/exprs.h (revision 2) @@ -0,0 +1,28 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _EXPRS_H_ +#define _EXPRS_H_ + +#include + +char * expr_localize(const char *); +int64_t expr_symcount(const char *) __attribute__((const)); +int64_t expr_nevaluate(const char *) __attribute__((const)); +int64_t expr_evaluate(const char *) __attribute__((const)); + +#endif Index: trunk/spar/segtab.h =================================================================== --- trunk/spar/segtab.h (nonexistent) +++ trunk/spar/segtab.h (revision 2) @@ -0,0 +1,49 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _SEGTAB_H_ +#define _SEGTAB_H_ + +#include + +#define SEG_INITSIZE 1024 + +struct seg +{ + struct op *code; + uint32_t max; + uint32_t pos; +}; + +#include "code.h" + +#define SEG_TEXT 0 +#define SEG_DATA 1 +#define SEG_BSS 2 +#define SEG_PILE 3 + +void init_seg(uint8_t, uint32_t); + +void set_current_segnum(uint8_t); +uint8_t get_current_segnum(void); + +struct seg *get_current_seg(void); +struct seg *get_seg(uint8_t); + +void adjust_segsize(struct seg *, uint32_t); + +#endif /* _SEGTAB_H_ */ Index: trunk/spar/code.c =================================================================== --- trunk/spar/code.c (nonexistent) +++ trunk/spar/code.c (revision 2) @@ -0,0 +1,101 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include +#include +#include +#include + +#include "code.h" +#include "segtab.h" + +void set_op(struct seg *seg, uint32_t pos, uint16_t op) +{ + seg->code[pos].op = op; +} + +uint16_t get_op(struct seg *seg, uint32_t pos) +{ + return seg->code[pos].op; +} + +void set_mode(struct seg *seg, uint32_t pos, uint8_t index, char mode) +{ + seg->code[pos].args[index].mode = mode; +} + +char get_mode(struct seg *seg, uint32_t pos, uint8_t index) +{ + return seg->code[pos].args[index].mode; +} + +void set_regnum(struct seg *seg, uint32_t pos, uint8_t index, uint16_t regnum) +{ + seg->code[pos].args[index].val.regnum = regnum; +} + +uint16_t get_regnum(struct seg *seg, uint32_t pos, uint8_t index) +{ + return seg->code[pos].args[index].val.regnum; +} + +void set_expr(struct seg *seg, uint32_t pos, uint8_t index, char * expr) +{ + seg->code[pos].args[index].val.expr = expr; +} + +char *get_expr(struct seg *seg, uint32_t pos, uint8_t index) +{ + return seg->code[pos].args[index].val.expr; +} + +void set_code(struct seg *seg, uint32_t pos, uint16_t code) +{ + seg->code[pos].code = code; +} + +uint16_t get_code(struct seg *seg, uint32_t pos) +{ + return seg->code[pos].code; +} + +void set_listing(struct seg *seg, uint32_t pos, const char *listing) +{ + if (listing != NULL) + { + strncpy(seg->code[pos].listing, listing, CODE_MAX_LISTLEN); + seg->code[pos].listing[CODE_MAX_LISTLEN-1] = '\0'; + } + else + { + seg->code[pos].listing[0] = '\0'; + } +} + +void trace_listing(struct seg *seg, uint32_t pos, const char *text) +{ + if (text != NULL) + { + strncat(seg->code[pos].listing, text, CODE_MAX_LISTLEN); + seg->code[pos].listing[CODE_MAX_LISTLEN-1] = '\0'; + } +} + +const char *get_listing(struct seg *seg, uint32_t pos) +{ + return seg->code[pos].listing; +} Index: trunk/spar/exprs.l =================================================================== --- trunk/spar/exprs.l (nonexistent) +++ trunk/spar/exprs.l (revision 2) @@ -0,0 +1,227 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +%option nounput + +%{ + +#include +#include + +#include "exprs.h" +#include "exprs.tab.h" +#include "spar.h" +#include "symtab.h" + +int exprsparse(int64_t *, int64_t *); + +static int allow_syms = 1; +static int resolve_syms = 1; +static int localize_syms = 0; +static char *localized_expr = NULL; + +#define YY_USER_ACTION \ +do { \ + if (localize_syms) { \ + localized_expr = xrealloc(localized_expr, \ + strlen(localized_expr) \ + + yyleng + 1); \ + strcat(localized_expr, yytext); \ + } \ +} while(0); + +%} + +BNUM (0b[0-1]+) +ONUM (0[0-7]*) +DNUM ([1-9][0-9]*) +XNUM (0x[0-9a-fA-F]+) +SYM (\.?[_\.a-zA-Z0-9@]+) + +%% + +"hi" return HI; +"lo" return LO; + +"(" return '('; +")" return ')'; + +"+" return '+'; +"-" return '-'; +"~" return '~'; +"!" return '!'; +"*" return '*'; +"/" return '/'; +"|/|" return CUDIV; +"%" return '%'; +"|%|" return CUMOD; +">>" return CSHR; +"<<" return CSHL; +">>>" return CSLR; +"<" return '<'; +">" return '>'; +"<=" return CLE; +">=" return CGE; +"|<|" return CULT; +"|>|" return CUGT; +"|<=|" return CULE; +"|>=|" return CUGE; +"==" return CEQU; +"!=" return CNEQ; +"&" return '&'; +"^" return '^'; +"|" return '|'; +"&&" return CLAND; +"||" return CLOR; +"?" return '?'; +":" return ':'; +"?" return CMAX; +"|?|" return CUMAX; + +{BNUM} { + exprslval.intval = strtol(yytext+2, NULL, 2); + return NUM; + } + +{ONUM} { + exprslval.intval = strtol(yytext, NULL, 8); + return NUM; + } + +{DNUM} { + exprslval.intval = strtol(yytext, NULL, 10); + return NUM; + } + +{XNUM} { + exprslval.intval = strtol(yytext+2, NULL, 16); + return NUM; + } + +{SYM} { + char *s = yytext; + + if (localize_syms) + { + s = localize_string(yytext); + localized_expr = xrealloc(localized_expr, + strlen(localized_expr) + + strlen(s) + - yyleng + 1); + strcpy(localized_expr + + strlen(localized_expr) + - yyleng, s); + } + else if (!allow_syms) + { + exprslval.intval = 0; + fprintf(stderr, "no symbol allowed here: `%s'\n", s); + error_count++; + } + else if (!resolve_syms) + { + exprslval.intval = 0; + } + else if (get_sym(s) == NULL) + { + exprslval.intval = 0; + fprintf(stderr, "symbol in expression not found: `%s'\n", s); + error_count++; + } + else + { + exprslval.intval = get_sym(s)->addr; + } + + return IDENT; + } + +[ \t\r\n]+ { /* ignore whitespace */ } + +%% + +int yywrap() +{ + return 1; +} + +char *expr_localize(const char *expr) +{ + int64_t value = 0; + int64_t symcount = 0; + + allow_syms = 1; + resolve_syms = 0; + localize_syms = 1; + localized_expr = xmalloc(1); + localized_expr[0] = '\0'; + + exprs_scan_string(expr); + exprsparse(&value, &symcount); + + return localized_expr; +} + +int64_t expr_symcount(const char *expr) +{ + int64_t value = 0; + int64_t symcount = 0; + + allow_syms = 1; + resolve_syms = 0; + localize_syms = 0; + localized_expr = NULL; + + exprs_scan_string(expr); + exprsparse(&value, &symcount); + + return symcount; +} + +int64_t expr_nevaluate(const char *expr) +{ + int64_t value = 0; + int64_t symcount = 0; + + allow_syms = 0; + resolve_syms = 0; + localize_syms = 0; + localized_expr = NULL; + + exprs_scan_string(expr); + exprsparse(&value, &symcount); + + return value; +} + +int64_t expr_evaluate(const char *expr) +{ + int64_t value = 0; + int64_t symcount = 0; + + allow_syms = 1; + resolve_syms = 1; + localize_syms = 0; + localized_expr = NULL; + + exprs_scan_string(expr); + exprsparse(&value, &symcount); + + return value; +} Index: trunk/spar/optab.h =================================================================== --- trunk/spar/optab.h (nonexistent) +++ trunk/spar/optab.h (revision 2) @@ -0,0 +1,140 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _OPTAB_H_ +#define _OPTAB_H_ + +#include + +#include "code.h" +#include "segtab.h" + +struct arg_info +{ + char type; + uint8_t width; + uint8_t offset; + int32_t min; + int32_t max; +}; + +struct op_info +{ + uint16_t opcode; + int8_t argc; + struct arg_info argv [CODE_MAX_ARGS]; +}; + +uint16_t get_op_code(struct seg *, uint32_t); +int8_t get_arg_count(struct seg *, uint32_t); +char get_arg_type(struct seg *, uint32_t, uint8_t); +uint8_t get_arg_width(struct seg *, uint32_t, uint8_t); +uint8_t get_arg_offset(struct seg *, uint32_t, uint8_t); +int32_t get_arg_min(struct seg *, uint32_t, uint8_t); +int32_t get_arg_max(struct seg *, uint32_t, uint8_t); + +extern const struct op_info optab []; + +#define DATA 0 +#define ADD 1 +#define SUB 2 +#define ADDC 3 +#define SUBC 4 +#define AND 5 +#define OR 6 +#define XOR 7 +#define MUL 8 +#define DIV 9 +#define UDIV 10 +#define LDIL 11 +#define LDIH 12 +#define LDIB 13 + +#define MOV 14 +#define MOD 15 +#define UMOD 16 +#define NOT 17 +#define NEG 18 +#define CMP 19 +#define ADDI 20 +#define CMPI 21 +#define SHL 22 +#define SHR 23 +#define SAR 24 +#define ROLC 25 +#define RORC 26 +#define BSET 27 +#define BCLR 28 +#define BTEST 29 + +#define LOAD 30 +#define STORE 31 +#define LOADL 32 +#define LOADH 33 +#define LOADB 34 +#define STOREL 35 +#define STOREH 36 +#define CALL 37 + +#define BR 38 +#define BRZ 39 +#define BRNZ 40 +#define BRLE 41 +#define BRLT 42 +#define BRGE 43 +#define BRGT 44 +#define BRULE 45 +#define BRULT 46 +#define BRUGE 47 +#define BRUGT 48 +#define SEXT 49 +#define LDVEC 50 +#define STVEC 51 + +#define JMP 52 +#define JMPZ 53 +#define JMPNZ 54 +#define JMPLE 55 +#define JMPLT 56 +#define JMPGE 57 +#define JMPGT 58 +#define JMPULE 59 +#define JMPULT 60 +#define JMPUGE 61 +#define JMPUGT 62 + +#define INTR 63 +#define GETIRA 64 +#define SETIRA 65 +#define GETFL 66 +#define SETFL 67 +#define GETSHFL 68 +#define SETSHFL 69 + +#define RETI 70 +#define NOP 71 +#define SEI 72 +#define CLI 73 +#define ERROR 74 + +#define ALIGN 75 +#define COMM 76 +#define LCOMM 77 +#define ORG 78 +#define SKIP 79 + +#endif /* _OPTAB_H_ */ Index: trunk/spar/spar.h =================================================================== --- trunk/spar/spar.h (nonexistent) +++ trunk/spar/spar.h (revision 2) @@ -0,0 +1,38 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _SPAR_H_ +#define _SPAR_H_ + +#include +#include + +extern char *command; + +extern uint32_t line_count; +extern uint32_t file_count; +extern uint32_t error_count; + +extern int seen_op; +extern int8_t args_to_match; + +void *xmalloc(size_t) __attribute__((malloc)); +void *xrealloc(void *, size_t) __attribute__((malloc)); +char *xstrdup(const char *) __attribute__((malloc)); +char *xsprintf(const char *, ...) __attribute__((malloc)); + +#endif /* _SPAR_H_ */ Index: trunk/spar/ui.c =================================================================== --- trunk/spar/ui.c (nonexistent) +++ trunk/spar/ui.c (revision 2) @@ -0,0 +1,40 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include + +#include "ui.h" + +const char * const options = "hvo:0:1:c:d:r:f:inlmse"; + +const struct option long_options [] = { + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { "output", required_argument, 0, 'o' }, + { "rom0file", required_argument, 0, '0' }, + { "rom1file", required_argument, 0, '1' }, + { "codesize", required_argument, 0, 'c' }, + { "datasize", required_argument, 0, 'd' }, + { "romsize", required_argument, 0, 'r' }, + { "filler", required_argument, 0, 'f' }, + { "intel", no_argument, 0, 'i' }, + { "dryrun", no_argument, 0, 'n' }, + { "download", no_argument, 0, 'l' }, + { "nointel", no_argument, 0, 'm' }, + { "nostart", no_argument, 0, 's' }, + { "noend", no_argument, 0, 'e' } +}; Index: trunk/spar/fixes.c =================================================================== --- trunk/spar/fixes.c (nonexistent) +++ trunk/spar/fixes.c (revision 2) @@ -0,0 +1,76 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include + +#include + +#include "spar.h" +#include "ui.h" +#include "code.h" +#include "exprs.h" +#include "fixes.h" +#include "optab.h" +#include "segtab.h" +#include "symtab.h" + +int fix_operands(struct seg *seg, uint32_t pos) +{ + uint8_t count = get_arg_count(seg, pos); + uint8_t index; + int retval = 0; + + for (index = 0; index < count; index++) + { + if (get_arg_type(seg, pos, index) == 'a') + { + set_expr(seg, pos, index, + xsprintf("(%s)-%d", get_expr(seg, pos, index), pos)); + } + } + + return retval; +} + +int fix_code(struct seg *seg, uint32_t pos) +{ + uint8_t count = get_arg_count(seg, pos); + uint8_t index; + uint16_t data; + + data = get_op_code(seg, pos); + for (index = 0; index < count; index++) + { + switch (get_arg_type(seg, pos, index)) + { + case 'r': + data |= (get_regnum(seg, pos, index) + & ((uint16_t)0xFFFF >> (16-get_arg_width(seg, pos, index)))) + << get_arg_offset(seg, pos, index); + break; + case 'n': + case 'a': + data |= (expr_evaluate(get_expr(seg, pos, index)) + & ((uint16_t)0xFFFF >> (16-get_arg_width(seg, pos, index)))) + << get_arg_offset(seg, pos, index); + break; + } + } + set_code(seg, pos, data); + + return 0; +} Index: trunk/spar/spar.l =================================================================== --- trunk/spar/spar.l (nonexistent) +++ trunk/spar/spar.l (revision 2) @@ -0,0 +1,844 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +%option nounput + +%{ +#include +#include +#include +#include +#include +#include + +#include "spar.h" +#include "ui.h" +#include "checks.h" +#include "code.h" +#include "emit.h" +#include "expand.h" +#include "exprs.h" +#include "fixes.h" +#include "optab.h" +#include "output.h" +#include "segtab.h" +#include "symtab.h" + +char *command = NULL; + +int8_t output_mode = DEFAULT_MODE; +FILE *output_file = NULL; +FILE *rom0_file = NULL; +FILE *rom1_file = NULL; + +uint32_t codesize = DEFAULT_CODESIZE; +uint32_t datasize = DEFAULT_DATASIZE; +uint32_t romsize = DEFAULT_ROMSIZE; +uint16_t filler = DEFAULT_FILLER; + +int nostart = 0; +int noend = 0; + +uint32_t line_count = 1; +uint32_t file_count = 0; +uint32_t error_count = 0; + +int seen_op = 0; +int8_t args_to_match = -1; + +/***************** WHAT TO DO ****************/ +int initialize(void); +int merge(void); +int postprocess(void); + +/* this does not really fit anywhere */ +void expand_mod(void); + +/***************** SHORTCUT ****************/ +#define MATCH_OP(X) \ +do { \ + struct seg *seg = get_current_seg(); \ + adjust_segsize(seg, seg->pos+1); \ + set_op(seg, seg->pos, (X)); \ + trace_listing(seg, seg->pos, yytext); \ + trace_listing(seg, seg->pos, "\t"); \ + seen_op = 1; \ + args_to_match = get_arg_count(seg, seg->pos)*2 - 1; \ +} while(0) + +%} + +REG (r[0-9]+) +NUM ((-?0[0-7]*)|(-?[1-9][0-9]*)|(-?0x[0-9a-fA-F]+)) +BNUM (0b[0-1]+) +SYM (\.?[_\.a-zA-Z0-9]+) +EXPR (([^ \t\r\n,;])|([^ \t\r\n,;][^,;\n]*[^ \t\r\n,;])) + +%% + +\.file[ \t]*\r?\n file_count++; + +\.text[ \t]*\r?\n set_current_segnum(SEG_TEXT); +\.data[ \t]*\r?\n set_current_segnum(SEG_DATA); +\.bss[ \t]*\r?\n set_current_segnum(SEG_BSS); + +\.align[ \t]{EXPR}\r?\n { + struct seg *seg = get_current_seg(); + char *s = xstrdup(yytext+7); + int32_t a = 1 << expr_nevaluate(s); + + while ((seg->pos % a) != 0) + { + if (get_current_segnum() == SEG_TEXT) + { + emit_nop(seg); + } + else + { + emit_zero(seg); + } + } + } + +\.comm[ \t]{SYM}[ \t]*,[ \t]*{EXPR}\r?\n { + int32_t i; + char *s = xstrdup(yytext+6); + char *t = s; + + t = strpbrk(s, ","); + *t++ = '\0'; + + s = localize_string(s); + check_sym_dup(s); + push_sym(s, SEG_BSS, get_seg(SEG_BSS)->pos); + trace_listing(get_seg(SEG_BSS), get_seg(SEG_BSS)->pos, s); + trace_listing(get_seg(SEG_BSS), get_seg(SEG_BSS)->pos, ":\t"); + + for (i=0; i < expr_nevaluate(t); i++) + { + emit_zero(get_seg(SEG_BSS)); + } + } + +\.lcomm[ \t]{SYM}[ \t]*,[ \t]*{EXPR}\r?\n { + int32_t i; + char *s = xstrdup(yytext+7); + char *t = s; + + t = strpbrk(s, ","); + *t++ = '\0'; + + s = localize_string(s); + check_sym_dup(s); + push_sym(s, SEG_BSS, get_seg(SEG_BSS)->pos); + trace_listing(get_seg(SEG_BSS), get_seg(SEG_BSS)->pos, s); + trace_listing(get_seg(SEG_BSS), get_seg(SEG_BSS)->pos, ":\t"); + + for (i=0; i < expr_nevaluate(t); i++) + { + emit_zero(get_seg(SEG_BSS)); + } + } + +\.org[ \t]{EXPR}\r?\n { + struct seg *seg = get_current_seg(); + char *s = xstrdup(yytext+6); + int32_t o = expr_nevaluate(s); + + check_org_advances(seg, o); + + while (seg->pos < o) + { + if (get_current_segnum() == SEG_TEXT) + { + emit_nop(seg); + } + else + { + emit_zero(seg); + } + } + } + +\.skip[ \t]{EXPR}\r?\n { + struct seg *seg = get_current_seg(); + char *s = xstrdup(yytext+6); + int32_t i; + + for (i = 0; i < expr_nevaluate(s); i++) + { + if (get_current_segnum() == SEG_TEXT) + { + emit_nop(seg); + } + else + { + emit_zero(seg); + } + } + } + +{SYM}: { + char *s; + struct seg *seg = get_current_seg(); + s = xstrdup(yytext); + s[yyleng-1] = '\0'; + s = localize_string(s); + check_sym_dup(s); + push_sym(s, get_current_segnum(), seg->pos); + trace_listing(seg, seg->pos, s); + trace_listing(seg, seg->pos, ":\t"); + } + +data MATCH_OP(DATA); +add MATCH_OP(ADD); +addc MATCH_OP(ADDC); +sub MATCH_OP(SUB); +subc MATCH_OP(SUBC); +and MATCH_OP(AND); +or MATCH_OP(OR); +xor MATCH_OP(XOR); +mul MATCH_OP(MUL); +div MATCH_OP(DIV); +udiv MATCH_OP(UDIV); +ldil MATCH_OP(LDIL); +ldih MATCH_OP(LDIH); +ldib MATCH_OP(LDIB); +mov MATCH_OP(MOV); +not MATCH_OP(NOT); +neg MATCH_OP(NEG); +cmp MATCH_OP(CMP); +addi MATCH_OP(ADDI); +cmpi MATCH_OP(CMPI); +shl MATCH_OP(SHL); +shr MATCH_OP(SHR); +sar MATCH_OP(SAR); +mod MATCH_OP(MOD); +umod MATCH_OP(UMOD); +rolc MATCH_OP(ROLC); +rorc MATCH_OP(RORC); +bset MATCH_OP(BSET); +bclr MATCH_OP(BCLR); +btest MATCH_OP(BTEST); +load MATCH_OP(LOAD); +store MATCH_OP(STORE); +loadl MATCH_OP(LOADL); +loadh MATCH_OP(LOADH); +loadb MATCH_OP(LOADB); +storel MATCH_OP(STOREL); +storeh MATCH_OP(STOREH); +call MATCH_OP(CALL); + +br MATCH_OP(BR); +brz MATCH_OP(BRZ); +brnz MATCH_OP(BRNZ); +brle MATCH_OP(BRLE); +brlt MATCH_OP(BRLT); +brge MATCH_OP(BRGE); +brgt MATCH_OP(BRGT); +brule MATCH_OP(BRULE); +brult MATCH_OP(BRULT); +bruge MATCH_OP(BRUGE); +brugt MATCH_OP(BRUGT); +sext MATCH_OP(SEXT); +ldvec MATCH_OP(LDVEC); +stvec MATCH_OP(STVEC); + +jmp MATCH_OP(JMP); +jmpz MATCH_OP(JMPZ); +jmpnz MATCH_OP(JMPNZ); +jmple MATCH_OP(JMPLE); +jmplt MATCH_OP(JMPLT); +jmpge MATCH_OP(JMPGE); +jmpgt MATCH_OP(JMPGT); +jmpule MATCH_OP(JMPULE); +jmpult MATCH_OP(JMPULT); +jmpuge MATCH_OP(JMPUGE); +jmpugt MATCH_OP(JMPUGT); +intr MATCH_OP(INTR); +getira MATCH_OP(GETIRA); +setira MATCH_OP(SETIRA); +getfl MATCH_OP(GETFL); +setfl MATCH_OP(SETFL); +getshfl MATCH_OP(GETSHFL); +setshfl MATCH_OP(SETSHFL); + +reti MATCH_OP(RETI); +nop MATCH_OP(NOP); +sei MATCH_OP(SEI); +cli MATCH_OP(CLI); +error MATCH_OP(ERROR); + +{REG} { + struct seg *seg = get_current_seg(); + int arg_index = get_arg_count(seg, seg->pos) - (args_to_match+1)/2; + + if (check_arg_count() || check_arg_type(seg, seg->pos, arg_index, 'r')) + YY_BREAK; + + set_regnum(seg, seg->pos, arg_index, strtol(yytext+1, NULL, 10)); + set_mode(seg, seg->pos, arg_index, 'r'); + trace_listing(seg, seg->pos, yytext); + args_to_match--; + } + +{EXPR} { + struct seg *seg = get_current_seg(); + int arg_index; + + if (!seen_op) + { + REJECT; + } + + arg_index = get_arg_count(seg, seg->pos) - (args_to_match+1)/2; + + if (check_arg_count() || check_arg_type(seg, seg->pos, arg_index, 'n')) + YY_BREAK; + + set_expr(seg, seg->pos, arg_index, expr_localize(yytext)); + set_mode(seg, seg->pos, arg_index, 'n'); + trace_listing(seg, seg->pos, yytext); + args_to_match--; + } + +, { + check_colon_ok(); + trace_listing(get_current_seg(), get_current_seg()->pos, ", "); + args_to_match--; + } + +;.* { /* ignore comments */ } + +[ \t\r]+ { /* ignore whitespace */ } + +\n+ { + check_premature(); + expand_mod(); + if (seen_op) + { + get_current_seg()->pos++; + seen_op = 0; + args_to_match = -1; + } + line_count += yyleng; + } + +<> { + check_premature(); + expand_mod(); + if (seen_op) + { + get_current_seg()->pos++; + seen_op = 0; + args_to_match = -1; + } + yyterminate(); + } + +. { + fprintf(stderr, "invalid input `%c' in line %lu\n", yytext[0], line_count); + error_count++; + } + +%% + +int initialize(void) +{ + init_symtab(); + + init_seg(SEG_DATA, SEG_INITSIZE/2); + init_seg(SEG_BSS, SEG_INITSIZE/2); + init_seg(SEG_TEXT, SEG_INITSIZE); + + set_current_segnum(SEG_TEXT); + + return 0; +} + +int merge(void) +{ + uint32_t pos; + int retval = 0; + + init_seg(SEG_PILE, SEG_INITSIZE); + + /* align .data to word boundary */ + if ((get_seg(SEG_DATA)->pos % 2) != 0) + { + emit_zero(get_seg(SEG_DATA)); + } + + /* align .bss to word boundary */ + if ((get_seg(SEG_BSS)->pos % 2) != 0) + { + emit_zero(get_seg(SEG_BSS)); + } + + /* check .data */ + for (pos = 0; pos < get_seg(SEG_DATA)->pos; pos += 2) + { + if ((get_op(get_seg(SEG_DATA), pos) != DATA) + || (get_op(get_seg(SEG_DATA), pos+1) != DATA)) + { + fprintf(stderr, "cannot initialize anything but `data' in .data\n"); + error_count++; + retval = 1; + } + } + + /* check .bss */ + for (pos = 0; pos < get_seg(SEG_BSS)->pos; pos++) + { + if ((get_op(get_seg(SEG_BSS), pos) != DATA) + || (expr_symcount(get_expr(get_seg(SEG_BSS), pos, 0)) > 0) + || (expr_evaluate(get_expr(get_seg(SEG_BSS), pos, 0)) != 0)) + { + fprintf(stderr, "cannot put anything but `data 0' in .bss\n"); + error_count++; + retval = 1; + } + } + + /* copy data from ROM */ + if (get_seg(SEG_DATA)->pos != 0) + { + emit_ldil(get_seg(SEG_PILE), 0, + xsprintf("lo(%d)", get_seg(SEG_DATA)->pos)); + emit_ldih(get_seg(SEG_PILE), 0, + xsprintf("hi(%d)", get_seg(SEG_DATA)->pos)); + + emit_ldil(get_seg(SEG_PILE), 1, + xsprintf("lo(%d)", datasize)); + emit_ldih(get_seg(SEG_PILE), 1, + xsprintf("hi(%d)", datasize)); + + emit_ldib(get_seg(SEG_PILE), 2, "0"); + push_sym("__init_data_loop__", SEG_PILE, get_seg(SEG_PILE)->pos); + trace_listing(get_seg(SEG_PILE), get_seg(SEG_PILE)->pos, + "__init_data_loop__:\t"); + emit_load(get_seg(SEG_PILE), 3, 1); + emit_store(get_seg(SEG_PILE), 3, 2); + emit_addi(get_seg(SEG_PILE), 1, "2"); + emit_addi(get_seg(SEG_PILE), 2, "2"); + emit_cmp(get_seg(SEG_PILE), 0, 2); + emit_brnz(get_seg(SEG_PILE), "__init_data_loop__"); + } + + /* clear .bss */ + if (get_seg(SEG_BSS)->pos != 0) + { + emit_ldil(get_seg(SEG_PILE), 0, + xsprintf("lo(%d+%d)", get_seg(SEG_DATA)->pos, + get_seg(SEG_BSS)->pos)); + emit_ldih(get_seg(SEG_PILE), 0, + xsprintf("hi(%d+%d)", get_seg(SEG_DATA)->pos, + get_seg(SEG_BSS)->pos)); + emit_ldib(get_seg(SEG_PILE), 3, "0"); + push_sym("__init_bss_loop__", SEG_PILE, get_seg(SEG_PILE)->pos); + trace_listing(get_seg(SEG_PILE), get_seg(SEG_PILE)->pos, + "__init_bss_loop__:\t"); + emit_store(get_seg(SEG_PILE), 3, 2); + emit_addi(get_seg(SEG_PILE), 2, "2"); + emit_cmp(get_seg(SEG_PILE), 0, 2); + emit_brnz(get_seg(SEG_PILE), "__init_bss_loop__"); + } + + reloc_syms(SEG_BSS, get_seg(SEG_DATA)->pos); + reloc_syms(SEG_TEXT, get_seg(SEG_PILE)->pos); + + for(pos = 0; pos < get_seg(SEG_TEXT)->pos; pos++) + { + emit_op(get_seg(SEG_PILE), get_seg(SEG_TEXT)->code[pos]); + } + + set_current_segnum(SEG_PILE); + + return retval; +} + +int postprocess(void) +{ + struct seg *seg; + uint32_t pos; + int retval = 0; + + if ((output_mode != MODE_DRYRUN) + && (check_code_size() + || check_data_size())) + { + retval = 1; + } + + seg = get_seg(SEG_PILE); + for (pos = 0; pos < seg->pos; pos++) + { + if (check_mnemonic(seg, pos)) + { + retval = 1; + } + if ((output_mode != MODE_DRYRUN) + && (fix_operands(seg, pos) + || check_ranges(seg, pos) + || fix_code(seg, pos))) + { + retval = 1; + } + } + + seg = get_seg(SEG_DATA); + for (pos = 0; pos < seg->pos; pos++) + { + if (check_mnemonic(seg, pos)) + { + retval = 1; + } + if ((output_mode != MODE_DRYRUN) + && (fix_operands(seg, pos) + || check_ranges(seg, pos) + || fix_code(seg, pos))) + { + retval = 1; + } + } + + return retval; +} + +/***************** LIB *****************/ + +void *xmalloc(size_t size) +{ + void *retval = malloc(size); + if (retval == NULL) + { + fprintf(stderr, "run out of memory\n"); + exit(EXIT_FAILURE); + } + return retval; +} + +void *xrealloc(void *ptr, size_t size) +{ + void *retval = realloc(ptr, size); + if (retval == NULL) + { + fprintf(stderr, "run out of memory\n"); + exit(EXIT_FAILURE); + } + return retval; +} + +char *xstrdup(const char *str) +{ + size_t len = strlen(str); + void *retval = xmalloc(len+1); + memcpy(retval, str, len+1); + return retval; +} + +char *xsprintf(const char *fmt, ...) +{ + va_list ap; + char *retval; + + va_start(ap, fmt); + vasprintf(&retval, fmt, ap); + va_end(ap); + + if (retval == NULL) + { + fprintf(stderr, "run out of memory\n"); + exit(EXIT_FAILURE); + } + + return retval; +} + +/***************** MAIN *****************/ + +int yywrap() +{ + return 1; +} + +int main(int argc, char **argv) +{ + int opt; + + int opterr = 0; + + int hopt = 0; + int vopt = 0; + + command = argv[0]; + + while (optind < argc) + { + if (strcmp(argv[optind], "-") == 0 || (argv[optind][0] != '-')) + { + opt = -1; + } + else + { + opt = getopt_long(argc, argv, options, long_options, 0); + } + + switch(opt) + { + case 'h': hopt++; break; + case 'v': vopt++; break; + case 'o': case '0': case '1': + case 'c': case 'd': case 'r': + case 'f': case 'i': case 'n': case 'l': + case 'm': case 's': case 'e': + break; + case '?': opterr = 1; break; + case -1: optind++; break; + } + } + + if (opterr) + { + printf("Usage:\n" + " %s [--intel|--nointel|--download|--dryrun]\n" + " [--codesize=*n*] [--datasize=*n*] [--romsize=*n*]\n" + " [--filler=*n*] [--output=file] [--rom0file=file] [--rom1file=file]\n" + " [--nostart] [--noend] file ...\n", command); + return EXIT_FAILURE; + } + + if (vopt) + { + printf("spar 0.2\n"); + return EXIT_SUCCESS; + } + + if (hopt) + { + printf("Usage:\n" + " %s [--intel|--nointel|--download|--dryrun]\n" + " [--codesize=*n*] [--datasize=*n*] [--romsize=*n*]\n" + " [--filler=*n*] [--output=file] [--rom0file=file] [--rom1file=file]\n" + " [--nostart] [--noend] file ...\n", command); + return EXIT_SUCCESS; + } + + optind = 1; + + initialize(); + + while (optind < argc) + { + if (strcmp(argv[optind], "-") == 0 || (argv[optind][0] != '-')) + { + opt = -1; + } + else + { + opt = getopt_long(argc, argv, options, long_options, 0); + } + + switch (opt) + { + case 'h': case 'v': + break; + case 'o': + if (strcmp(optarg, "-") == 0) + { + output_file = stdout; + } + else + { + output_file = fopen(optarg, "w"); + if (output_file == NULL) + { + fprintf(stderr, "cannot open file %s\n", optarg); + return EXIT_FAILURE; + } + } + break; + case '0': + if (strcmp(optarg, "-") == 0) + { + rom0_file = stdout; + } + else + { + rom0_file = fopen(optarg, "w"); + if (rom0_file == NULL) + { + fprintf(stderr, "cannot open file %s\n", optarg); + return EXIT_FAILURE; + } + } + break; + case '1': + if (strcmp(optarg, "-") == 0) + { + rom1_file = stdout; + } + else + { + rom1_file = fopen(optarg, "w"); + if (rom1_file == NULL) + { + fprintf(stderr, "cannot open file %s\n", optarg); + return EXIT_FAILURE; + } + } + break; + case 'c': + { + char * errptr = NULL; + romsize = strtol(optarg, &errptr, 0); + if (*errptr != '\0') + { + fprintf(stderr, "invalid codesize %s\n", optarg); + return EXIT_FAILURE; + } + } + break; + case 'd': + { + char * errptr = NULL; + romsize = strtol(optarg, &errptr, 0); + if (*errptr != '\0') + { + fprintf(stderr, "invalid datasize %s\n", optarg); + return EXIT_FAILURE; + } + } + break; + case 'r': + { + char * errptr = NULL; + romsize = strtol(optarg, &errptr, 0); + if (*errptr != '\0') + { + fprintf(stderr, "invalid romsize %s\n", optarg); + return EXIT_FAILURE; + } + } + break; + case 'f': + { + char * errptr = NULL; + filler = strtol(optarg, &errptr, 0); + if (*errptr != '\0') + { + fprintf(stderr, "invalid filler %s\n", optarg); + return EXIT_FAILURE; + } + } + break; + case 'i': output_mode = MODE_INTEL; break; + case 'n': output_mode = MODE_DRYRUN; break; + case 'l': output_mode = MODE_DOWNLOAD; break; + case 'm': output_mode = MODE_MIF; break; + case 's': nostart = 1; break; + case 'e': noend = 1; break; + case '?': break; + case -1: + if (argv[optind] == NULL) + break; + if (strcmp(argv[optind], "-") == 0) + { + yyin = stdin; + } + else + { + yyin = fopen(argv[optind], "r"); + if (yyin == NULL) + { + fprintf(stderr, "cannot open file %s\n", argv[optind]); + return EXIT_FAILURE; + } + } + yylex(); + file_count++; + + optind++; + break; + } + } + + if (output_file == NULL) + { + output_file = stdout; + } + if (rom0_file == NULL) + { + rom0_file = stdout; + } + if (rom1_file == NULL) + { + rom1_file = stdout; + } + + if (file_count == 0) + { + yyin = stdin; + yylex(); + } + + merge(); + + postprocess(); + + if (error_count != 0) + { + fprintf(stderr, "found %lu error(s)\n", error_count); + return EXIT_FAILURE; + } + + if (output_file == NULL) + { + output_file = stdout; + } + if (rom0_file == NULL) + { + rom0_file = stdout; + } + if (rom1_file == NULL) + { + rom1_file = stdout; + } + + switch (output_mode) + { + case MODE_DRYRUN: break; + case MODE_DOWNLOAD: print_download(output_file, rom0_file, rom1_file); break; + case MODE_INTEL: print_intel(output_file, rom0_file, rom1_file); break; + case MODE_MIF: print_mif(output_file, rom0_file, rom1_file); break; + } + + if (output_file != stdout) + { + fclose(output_file); + } + if (rom0_file != stdout) + { + fclose(rom0_file); + } + if (rom1_file != stdout) + { + fclose(rom1_file); + } + + return EXIT_SUCCESS; +} Index: trunk/spar/expand.c =================================================================== --- trunk/spar/expand.c (nonexistent) +++ trunk/spar/expand.c (revision 2) @@ -0,0 +1,59 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include "spar.h" +#include "expand.h" +#include "code.h" +#include "optab.h" + +void expand_mod(void) +{ + struct op o = get_current_seg()->code[get_current_seg()->pos]; + + if ((o.op == MOD) || (o.op == UMOD)) + { + if (o.args[0].val.regnum != o.args[2].val.regnum) + { + struct seg* seg = get_current_seg(); + + set_op(seg, seg->pos, MOV); + set_mode(seg, seg->pos, 0, 'r'); + set_regnum(seg, seg->pos, 0, o.args[2].val.regnum); + set_mode(seg, seg->pos, 1, 'r'); + set_regnum(seg, seg->pos, 1, o.args[0].val.regnum); + set_listing(seg, seg->pos, xsprintf("mov\tr%d, r%d", + o.args[2].val.regnum, + o.args[0].val.regnum)); + + seg->pos++; + adjust_segsize(seg, seg->pos+1); + + set_op(seg, seg->pos, o.op); + set_mode(seg, seg->pos, 0, 'r'); + set_regnum(seg, seg->pos, 0, o.args[2].val.regnum); + set_mode(seg, seg->pos, 1, 'r'); + set_regnum(seg, seg->pos, 1, o.args[1].val.regnum); + set_mode(seg, seg->pos, 2, 'r'); + set_regnum(seg, seg->pos, 2, 0); /* this should never be used */ + set_listing(seg, seg->pos, xsprintf("%s\tr%d, r%d, r%d", + o.op == MOD ? "mod" : "umod", + o.args[2].val.regnum, + o.args[1].val.regnum, + o.args[2].val.regnum)); + } + } +} Index: trunk/spar/code.h =================================================================== --- trunk/spar/code.h (nonexistent) +++ trunk/spar/code.h (revision 2) @@ -0,0 +1,60 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _CODE_H_ +#define _CODE_H_ + +#include + +#define CODE_MAX_ARGS 3 +#define CODE_MAX_LISTLEN 32 + +struct arg +{ + char mode; + union + { + uint16_t regnum; + char *expr; + } val; +}; + +struct op +{ + uint16_t op; + struct arg args [CODE_MAX_ARGS]; + uint16_t code; + char listing [CODE_MAX_LISTLEN]; +}; + +#include "segtab.h" + +void set_op(struct seg *, uint32_t, uint16_t); +uint16_t get_op(struct seg *, uint32_t); +void set_mode(struct seg *, uint32_t, uint8_t, char); +char get_mode(struct seg *, uint32_t, uint8_t); +void set_regnum(struct seg *, uint32_t, uint8_t, uint16_t); +uint16_t get_regnum(struct seg *, uint32_t, uint8_t); +void set_expr(struct seg *, uint32_t, uint8_t, char *); +char * get_expr(struct seg *, uint32_t, uint8_t); +void set_code(struct seg *, uint32_t, uint16_t); +uint16_t get_code(struct seg *, uint32_t); +void set_listing(struct seg *, uint32_t, const char *); +void trace_listing(struct seg *, uint32_t, const char *); +const char *get_listing(struct seg *, uint32_t); + +#endif /* _CODE_H_ */ Index: trunk/spar/ui.h =================================================================== --- trunk/spar/ui.h (nonexistent) +++ trunk/spar/ui.h (revision 2) @@ -0,0 +1,49 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _UI_H_ +#define _UI_H_ + +#include +#include +#include + +#define MODE_DRYRUN 0 +#define MODE_DOWNLOAD 1 +#define MODE_INTEL 2 +#define MODE_MIF 3 + +extern int8_t output_mode; + +extern uint32_t codesize; +extern uint32_t datasize; +extern uint32_t romsize; +extern uint16_t filler; + +extern int nostart; +extern int noend; + +#define DEFAULT_MODE MODE_MIF +#define DEFAULT_CODESIZE 8192 +#define DEFAULT_DATASIZE 8192 +#define DEFAULT_ROMSIZE 256 +#define DEFAULT_FILLER 0xFFFF + +extern const char * const options; +extern const struct option long_options []; + +#endif /* _UI_H_ */ Index: trunk/spar/fixes.h =================================================================== --- trunk/spar/fixes.h (nonexistent) +++ trunk/spar/fixes.h (revision 2) @@ -0,0 +1,28 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _FIXES_H_ +#define _FIXES_H_ + +#include + +#include "segtab.h" + +int fix_operands(struct seg *, uint32_t); +int fix_code(struct seg *, uint32_t); + +#endif /* _FIXES_H_ */ Index: trunk/spar/expand.h =================================================================== --- trunk/spar/expand.h (nonexistent) +++ trunk/spar/expand.h (revision 2) @@ -0,0 +1,23 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifndef _EXPAND_H_ +#define _EXPAND_H_ + +void expand_mod(void); + +#endif /* _EXPAND_H_ */ Index: trunk/spar/exprs.y =================================================================== --- trunk/spar/exprs.y (nonexistent) +++ trunk/spar/exprs.y (revision 2) @@ -0,0 +1,260 @@ +/* This file is part of the assembler "spar" for marca. + Copyright (C) 2007 Wolfgang Puffitsch + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +%{ + +#include +#include + +#include "exprs.h" + +int exprslex(void); +void yyerror(int64_t *, const char *); + +%} + +%union { + int64_t intval; +} + +%parse-param { + int64_t *retval, int64_t *symcount +} + +%token NUM IDENT + +%token CUMOD CEQU CUGT CSHR CUMIN CLE CNEQ CMIN CLAND +%token CGE CUDIV CUGE CULE CLOR CULT CSHL CMAX CUMAX CSLR +%token HI LO + +%type PrimaryExpr UnaryExpr MultExpr AddExpr ShiftExpr +%type RelatExpr EqualExpr AndExpr XorExpr OrExpr +%type LAndExpr LOrExpr CondExpr MinMaxExpr HiLoExpr Expr + +%start Expr + +%% + +PrimaryExpr : NUM + { $$ = $1; + } + | IDENT + { (*symcount)++; + $$ = $1; + } + | '(' Expr ')' + { $$ = $2; + } +; + +UnaryExpr : PrimaryExpr + | '+' UnaryExpr + { $$ = $2; + } + | '-' UnaryExpr + { $$ = -$2; + } + | '~' UnaryExpr + { $$ = ~$2; + } + | '!' UnaryExpr + { $$ = !$2; + } +; + +MultExpr : UnaryExpr + | MultExpr '*' UnaryExpr + { $$ = $1 * $3; + } + | MultExpr '/' UnaryExpr + { + if ($3 == 0) + { + fprintf(stderr, "division by zero"); + $$ = 0; + } + else + { + $$ = $1 / $3; + } + } + | MultExpr CUDIV UnaryExpr + { + if ($3 == 0) + { + fprintf(stderr, "division by zero"); + $$ = 0; + } + else + { + $$ = (uint64_t)$1 / (uint64_t)$3; + } + } + | MultExpr '%' UnaryExpr + { + if ($3 == 0) + { + fprintf(stderr, "modulo zero"); + $$ = 0; + } + else + { + $$ = $1 % $3; + } + } + | MultExpr CUMOD UnaryExpr + { + if ($3 == 0) + { + fprintf(stderr, "modulo zero"); + $$ = 0; + } + else + { + $$ = (uint64_t)$1 % (uint64_t)$3; + } + } +; + +AddExpr : MultExpr + | AddExpr '+' MultExpr + { $$ = $1 + $3; + } + | AddExpr '-' MultExpr + { $$ = $1 - $3; + } +; + +ShiftExpr : AddExpr + | ShiftExpr CSHR AddExpr + { $$ = $1 >> $3; + } + | ShiftExpr CSHL AddExpr + { $$ = $1 << $3; + } + | ShiftExpr CSLR AddExpr + { $$ = (uint64_t)$1 >> $3; + } +; + +RelatExpr : ShiftExpr + | RelatExpr '<' ShiftExpr + { $$ = $1 < $3; + } + | RelatExpr '>' ShiftExpr + { $$ = $1 > $3; + } + | RelatExpr CLE ShiftExpr + { $$ = $1 <= $3; + } + | RelatExpr CGE ShiftExpr + { $$ = $1 >= $3; + } + | RelatExpr CULT ShiftExpr + { $$ = (uint64_t)$1 < (uint64_t)$3; + } + | RelatExpr CUGT ShiftExpr + { $$ = (uint64_t)$1 > (uint64_t)$3; + } + | RelatExpr CULE ShiftExpr + { $$ = (uint64_t)$1 <= (uint64_t)$3; + } + | RelatExpr CUGE ShiftExpr + { $$ = (uint64_t)$1 >= (uint64_t)$3; + } +; + +EqualExpr : RelatExpr + | EqualExpr CEQU RelatExpr + { $$ = $1 == $3; + } + | EqualExpr CNEQ RelatExpr + { $$ = $1 != $3; + } +; + +AndExpr : EqualExpr + | AndExpr '&' EqualExpr + { $$ = $1 & $3; + } +; + +XorExpr : AndExpr + | XorExpr '^' AndExpr + { $$ = $1 ^ $3; + } +; + +OrExpr : XorExpr + | OrExpr '|' XorExpr + { $$ = $1 | $3; + } +; + +LAndExpr : OrExpr + | LAndExpr CLAND OrExpr + { $$ = $1 && $3; + } +; + +LOrExpr : LAndExpr + | LOrExpr CLOR LAndExpr + { $$ = $1 || $3; + } +; + +CondExpr : LOrExpr + | LOrExpr '?' Expr ':' CondExpr + { $$ = $1 ? $3 : $5; + } +; + +MinMaxExpr : CondExpr + | MinMaxExpr CMIN CondExpr + { $$ = $1 < $3 ? $1 : $3; + } + | MinMaxExpr CMAX CondExpr + { $$ = $1 > $3 ? $1 : $3; + } + | MinMaxExpr CUMIN CondExpr + { $$ = (uint64_t)$1 < (uint64_t)$3 ? $1 : $3; + } + | MinMaxExpr CUMAX CondExpr + { $$ = (uint64_t)$1 > (uint64_t)$3 ? $1 : $3; + } +; + +HiLoExpr : MinMaxExpr + | HI '(' MinMaxExpr ')' + { $$ = ($3 >> 8) & 0xFF; + } + | LO '(' MinMaxExpr ')' + { $$ = $3 & 0xFF; + } + +Expr: HiLoExpr + { *retval = $1; + } +; + +%% + +void yyerror(int64_t *r, const char *msg) +{ + fprintf(stderr, "within expression: %s\n", msg); +} + Index: trunk/spar/Makefile =================================================================== --- trunk/spar/Makefile (nonexistent) +++ trunk/spar/Makefile (revision 2) @@ -0,0 +1,43 @@ +CC=gcc +LEX=flex -l +YACC=bison -y + +CFLAGS = -ansi -pedantic -D_GNU_SOURCE -Wall -Wno-format -g +LFLAGS = -Ce -8 +YFLAGS = -d + +all: as1 + +as1: checks.o code.o emit.o expand.o fixes.o optab.o output.o segtab.o \ + spar.o symtab.o ui.o lex.exprs.o exprs.tab.o + $(CC) -o $@ $^ + +spar.o: spar.c spar.h ui.h checks.h segtab.h code.h emit.h exprs.h \ + fixes.h optab.h output.h symtab.h +spar.o: spar.c exprs.h exprs.tab.h spar.h symtab.h +spar.c: spar.l + +checks.o: checks.c spar.h ui.h checks.h segtab.h code.h exprs.h optab.h \ + symtab.h +code.o: code.c code.h segtab.h +emit.o: emit.c spar.h optab.h code.h segtab.h emit.h exprs.h +expand.o: expand.c spar.h expand.h code.h segtab.h optab.h +fixes.o: fixes.c spar.h ui.h code.h segtab.h exprs.h fixes.h optab.h \ + symtab.h +optab.o: optab.c optab.h code.h segtab.h +output.o: output.c spar.h ui.h output.h segtab.h code.h +segtab.o: segtab.c spar.h segtab.h code.h +symtab.o: symtab.c spar.h symtab.h +ui.o: ui.c ui.h + +lex.exprs.o: lex.exprs.c exprs.h exprs.tab.h spar.h symtab.h +lex.exprs.c: exprs.l exprs.tab.h exprs.h + $(LEX) $(LFLAGS) -Pexprs exprs.l + +exprs.tab.o: exprs.tab.c +exprs.tab.c exprs.tab.h: exprs.y exprs.h + $(YACC) $(YFLAGS) -b exprs -p exprs exprs.y + sed -i '/^yydestruct (/ N; s/\n[ \t]*int64_t \*retval,//' exprs.tab.c + +clean: + rm -f as1 *.o exprs.tab.h exprs.tab.c lex.exprs.c spar.c Index: trunk/sim/sim1.vwf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/sim/sim1.vwf =================================================================== --- trunk/sim/sim1.vwf (nonexistent) +++ trunk/sim/sim1.vwf (revision 2)
trunk/sim/sim1.vwf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/Makefile =================================================================== --- trunk/Makefile (nonexistent) +++ trunk/Makefile (revision 2) @@ -0,0 +1,26 @@ +all: marca spar doc + +marca:: + echo "You have to build marca from within quartus." + +spar:: + cd spar && make + +doc:: + cd doc && make + +dist:: + tar -czvf marca.tar.gz vhdl/ sim/ spar/ \ + quartus/marca.qpf quartus/marca.qsf \ + quartus/marca.pin \ + doc/isa.tex doc/implementation.tex \ + doc/factorial.s doc/uart_reverse.s \ + doc/marca.dia doc/marca.eps doc/marca.png \ + doc/uart_sim.eps doc/uart_sim.png \ + doc/Makefile \ + Makefile gpl.txt \ + --exclude '*~' + +clean:: + make -C spar clean + make -C doc clean \ No newline at end of file Index: trunk/vhdl/fetch_ent.vhd =================================================================== --- trunk/vhdl/fetch_ent.vhd (nonexistent) +++ trunk/vhdl/fetch_ent.vhd (revision 2) @@ -0,0 +1,51 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA fetch stage +------------------------------------------------------------------------------- +-- entity definition for the instruction-fetch pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity fetch is + + port ( + clock : in std_logic; + reset : in std_logic; + + hold : in std_logic; + + pcena : in std_logic; + pc_in : in std_logic_vector(REG_WIDTH-1 downto 0); + pc_out : out std_logic_vector(REG_WIDTH-1 downto 0); + + src1 : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + src2 : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + dest : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + instr : out std_logic_vector(PDATA_WIDTH-1 downto 0)); + +end fetch; Index: trunk/vhdl/data_memory.vhd =================================================================== --- trunk/vhdl/data_memory.vhd (nonexistent) +++ trunk/vhdl/data_memory.vhd (revision 2) @@ -0,0 +1,182 @@ +-- megafunction wizard: %RAM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: data_memory.vhd +-- Megafunction Name(s): +-- altsyncram +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 6.0 Build 202 06/20/2006 SP 1 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2006 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY data_memory IS + PORT + ( + address : IN STD_LOGIC_VECTOR (11 DOWNTO 0); + clken : IN STD_LOGIC ; + clock : IN STD_LOGIC ; + data : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + wren : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END data_memory; + + +ARCHITECTURE SYN OF data_memory IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_aclr_a : STRING; + indata_aclr_a : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + power_up_uninitialized : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL; + wrcontrol_aclr_a : STRING + ); + PORT ( + clocken0 : IN STD_LOGIC ; + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (11 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0); + data_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + indata_aclr_a => "NONE", + intended_device_family => "Cyclone", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 4096, + operation_mode => "SINGLE_PORT", + outdata_aclr_a => "NONE", + outdata_reg_a => "UNREGISTERED", + power_up_uninitialized => "FALSE", + widthad_a => 12, + width_a => 8, + width_byteena_a => 1, + wrcontrol_aclr_a => "NONE" + ) + PORT MAP ( + clocken0 => clken, + wren_a => wren, + clock0 => clock, + address_a => address, + data_a => data, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrData NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "1" +-- Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegData NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +-- Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "12" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: INDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +-- Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: CONSTANT: WRCONTROL_ACLR_A STRING "NONE" +-- Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL address[11..0] +-- Retrieval info: USED_PORT: clken 0 0 0 0 INPUT NODEFVAL clken +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +-- Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL data[7..0] +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0] +-- Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL wren +-- Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: @clocken0 0 0 0 0 clken 0 0 0 0 +-- Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0 +-- Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_memory.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_memory.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_memory.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_memory.bsf TRUE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_memory_inst.vhd FALSE Index: trunk/vhdl/code_memory.vhd =================================================================== --- trunk/vhdl/code_memory.vhd (nonexistent) +++ trunk/vhdl/code_memory.vhd (revision 2) @@ -0,0 +1,166 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: code_memory.vhd +-- Megafunction Name(s): +-- altsyncram +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 6.0 Build 202 06/20/2006 SP 1 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2006 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY code_memory IS + GENERIC + ( + init_file : STRING + ); + PORT + ( + address : IN STD_LOGIC_VECTOR (12 DOWNTO 0); + clken : IN STD_LOGIC ; + clock : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0) + ); +END code_memory; + + +ARCHITECTURE SYN OF code_memory IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (15 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_aclr_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + clocken0 : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (12 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(15 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + init_file => init_file, + intended_device_family => "Cyclone", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 8192, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "UNREGISTERED", + widthad_a => 13, + width_a => 16, + width_byteena_a => 1 + ) + PORT MAP ( + clocken0 => clken, + clock0 => clock, + address_a => address, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "1" +-- Retrieval info: PRIVATE: Clken NUMERIC "1" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "src/code.mif" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "8192" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "13" +-- Retrieval info: PRIVATE: WidthData NUMERIC "16" +-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: INIT_FILE STRING "src/code.mif" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "8192" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "13" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "16" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL address[12..0] +-- Retrieval info: USED_PORT: clken 0 0 0 0 INPUT NODEFVAL clken +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +-- Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0] +-- Retrieval info: CONNECT: @address_a 0 0 13 0 address 0 0 13 0 +-- Retrieval info: CONNECT: q 0 0 16 0 @q_a 0 0 16 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: @clocken0 0 0 0 0 clken 0 0 0 0 +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: GEN_FILE: TYPE_NORMAL code_memory.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL code_memory.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL code_memory.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL code_memory.bsf TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL code_memory_inst.vhd FALSE Index: trunk/vhdl/execute.vhd =================================================================== --- trunk/vhdl/execute.vhd (nonexistent) +++ trunk/vhdl/execute.vhd (revision 2) @@ -0,0 +1,291 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA execution stage +------------------------------------------------------------------------------- +-- architecture of the execution pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; + +architecture behaviour of execute is + +component alu is + port ( + clock : in std_logic; + reset : in std_logic; + busy : out std_logic; + op : in ALU_OP; + a : in std_logic_vector(REG_WIDTH-1 downto 0); + b : in std_logic_vector(REG_WIDTH-1 downto 0); + i : in std_logic_vector(REG_WIDTH-1 downto 0); + pc : in std_logic_vector(REG_WIDTH-1 downto 0); + intr : in std_logic; + exc : out std_logic; + iena : out std_logic; + pcchg : out std_logic; + result : out std_logic_vector(REG_WIDTH-1 downto 0)); +end component; + +component mem is + port ( + clock : in std_logic; + reset : in std_logic; + op : in MEM_OP; + address : in std_logic_vector(REG_WIDTH-1 downto 0); + data : in std_logic_vector(REG_WIDTH-1 downto 0); + exc : out std_logic; + busy : out std_logic; + result : out std_logic_vector(REG_WIDTH-1 downto 0); + intrs : out std_logic_vector(VEC_COUNT-1 downto 3); + ext_in : in std_logic_vector(IN_BITS-1 downto 0); + ext_out : out std_logic_vector(OUT_BITS-1 downto 0)); +end component; + +component intr is + port ( + clock : in std_logic; + reset : in std_logic; + enable : in std_logic; + trigger : in std_logic_vector(VEC_COUNT-1 downto 1); + op : in INTR_OP; + a : in std_logic_vector(REG_WIDTH-1 downto 0); + i : in std_logic_vector(REG_WIDTH-1 downto 0); + pc : in std_logic_vector(REG_WIDTH-1 downto 0); + exc : out std_logic; + pcchg : out std_logic; + result : out std_logic_vector(REG_WIDTH-1 downto 0)); +end component; + +signal any_busy : std_logic; + +signal alu_iena : std_logic; +signal alu_exc : std_logic; +signal alu_busy : std_logic; +signal alu_pcchg : std_logic; +signal alu_result : std_logic_vector(REG_WIDTH-1 downto 0); + +signal mem_exc : std_logic; +signal mem_busy : std_logic; +signal mem_result : std_logic_vector(REG_WIDTH-1 downto 0); +signal mem_intrs : std_logic_vector(VEC_COUNT-1 downto 3); + +signal intr_enable : std_logic; +signal intr_exc : std_logic; +signal intr_pcchg : std_logic; +signal intr_result : std_logic_vector(REG_WIDTH-1 downto 0); + +signal pc_reg : std_logic_vector(REG_WIDTH-1 downto 0); + +signal src1_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal src2_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal dest_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0); + +signal op1_reg : std_logic_vector(REG_WIDTH-1 downto 0); +signal op2_reg : std_logic_vector(REG_WIDTH-1 downto 0); +signal imm_reg : std_logic_vector(REG_WIDTH-1 downto 0); + +signal op1_fwed : std_logic_vector(REG_WIDTH-1 downto 0); +signal op2_fwed : std_logic_vector(REG_WIDTH-1 downto 0); + +signal aop_reg : ALU_OP; +signal mop_reg : MEM_OP; +signal iop_reg : INTR_OP; + +signal unit_reg : UNIT_SELECTOR; +signal target_reg : TARGET_SELECTOR; + +signal stall_cnt : std_logic_vector(1 downto 0); -- prohibiting +signal next_stall_cnt : std_logic_vector(1 downto 0); -- interrupts during reti + +begin -- behaviour + + -- interrupts do not work while jumping + intr_enable <= alu_iena and zero(stall_cnt) and not any_busy; + + alu_unit : alu + port map ( + clock => clock, + reset => reset, + op => aop_reg, + a => op1_fwed, + b => op2_fwed, + i => imm_reg, + pc => pc_reg, + intr => intr_exc, + exc => alu_exc, + busy => alu_busy, + iena => alu_iena, + pcchg => alu_pcchg, + result => alu_result); + + mem_unit : mem + port map ( + clock => clock, + reset => reset, + op => mop_reg, + address => op2_fwed, + data => op1_fwed, + exc => mem_exc, + busy => mem_busy, + result => mem_result, + intrs => mem_intrs, + ext_in => ext_in, + ext_out => ext_out); + + intr_unit : intr + port map ( + clock => clock, + reset => reset, + enable => intr_enable, + trigger(EXC_ALU) => alu_exc, + trigger(EXC_MEM) => mem_exc, + trigger(VEC_COUNT-1 downto 3) => mem_intrs, + op => iop_reg, + a => op1_fwed, + i => imm_reg, + pc => pc_reg, + exc => intr_exc, + pcchg => intr_pcchg, + result => intr_result); + + syn_proc: process (clock, reset) + begin -- process syn_proc + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + stall_cnt <= (others => '0'); + pc_reg <= (others => '0'); + src1_reg <= (others => '0'); + src2_reg <= (others => '0'); + dest_reg <= (others => '0'); + aop_reg <= ALU_NOP; + mop_reg <= MEM_NOP; + iop_reg <= INTR_NOP; + op1_reg <= (others => '0'); + op2_reg <= (others => '0'); + imm_reg <= (others => '0'); + unit_reg <= UNIT_ALU; + target_reg <= TARGET_NONE; + elsif clock'event and clock = '1' then -- rising clock edge + if any_busy = '0' then + stall_cnt <= next_stall_cnt; + if stall = '1' then + pc_reg <= (others => '0'); + src1_reg <= (others => '0'); + src2_reg <= (others => '0'); + dest_reg <= (others => '0'); + aop_reg <= ALU_NOP; + mop_reg <= MEM_NOP; + iop_reg <= INTR_NOP; + op1_reg <= (others => '0'); + op2_reg <= (others => '0'); + imm_reg <= (others => '0'); + unit_reg <= UNIT_ALU; + target_reg <= TARGET_NONE; + else + pc_reg <= pc_in; + dest_reg <= dest_in; + src1_reg <= src1; + src2_reg <= src2; + aop_reg <= aop; + mop_reg <= mop; + iop_reg <= iop; + op1_reg <= op1; + op2_reg <= op2; + imm_reg <= imm; + unit_reg <= unit; + target_reg <= target_in; + end if; + end if; + end if; + end process syn_proc; + + stalling: process (stall, stall_cnt) + begin -- process hold_pc + + next_stall_cnt <= std_logic_vector(unsigned(stall_cnt) - 1); + if zero(stall_cnt) = '1' then + next_stall_cnt <= "00"; + end if; + if stall = '1' then + next_stall_cnt <= "11"; + end if; + + end process stalling; + + business: process (any_busy, alu_busy, mem_busy) + begin -- process business + any_busy <= alu_busy or mem_busy; + busy <= any_busy; + end process business; + + feedthrough: process (pc_reg, dest_reg, unit_reg, target_reg, op2_fwed, intr_exc) + begin -- process feedthrough + if unit_reg /= UNIT_CALL then + pc_out <= pc_reg; + else + pc_out <= op2_fwed; + end if; + dest_out <= dest_reg; + if intr_exc = '1' then + target_out <= TARGET_PC; + else + target_out <= target_reg; + end if; + end process feedthrough; + + forward: process (src1_reg, src2_reg, op1_reg, op2_reg, fw_ena, fw_dest, fw_val) + begin -- process forward + op1_fwed <= op1_reg; + op2_fwed <= op2_reg; + if fw_ena = '1' then + if src1_reg = fw_dest then + op1_fwed <= fw_val; + end if; + if src2_reg = fw_dest then + op2_fwed <= fw_val; + end if; + end if; + end process forward; + + select_result: process(unit_reg, alu_result, mem_result, intr_result, pc_reg, + alu_pcchg, intr_pcchg, + intr_exc) + begin -- process select_result + case unit_reg is + when UNIT_ALU => result <= alu_result; + when UNIT_MEM => result <= mem_result; + when UNIT_INTR => result <= intr_result; + when UNIT_CALL => result <= std_logic_vector(unsigned(pc_reg) + 1); + when others => null; + end case; + if intr_exc = '1' then + result <= intr_result; + end if; + pcchg <= alu_pcchg or intr_pcchg; + end process select_result; + +end behaviour; Index: trunk/vhdl/marca.vht =================================================================== --- trunk/vhdl/marca.vht (nonexistent) +++ trunk/vhdl/marca.vht (revision 2) @@ -0,0 +1,492 @@ +-- Copyright (C) 1991-2006 Altera Corporation +-- Your use of Altera Corporation's design tools, logic functions +-- and other software and tools, and its AMPP partner logic +-- functions, and any output files any of the foregoing +-- (including device programming or simulation files), and any +-- associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License +-- Subscription Agreement, Altera MegaCore Function License +-- Agreement, or other applicable license agreement, including, +-- without limitation, that your use is for the sole purpose of +-- programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the +-- applicable agreement for further details. + +-- ***************************************************************************** +-- This file contains a Vhdl test bench with test vectors .The test vectors +-- are exported from a vector file in the Quartus Waveform Editor and apply to +-- the top level entity of the current Quartus project .The user can use this +-- testbench to simulate his design using a third-party simulation tool . +-- ***************************************************************************** +-- Generated on "12/14/2006 19:48:14" + +-- Vhdl Self-Checking Test Bench (with test vectors) for design : marca +-- +-- Simulation tool : 3rd Party +-- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY STD; +USE STD.textio.ALL; + +PACKAGE marca_vhd_tb_types IS +-- input port types +SUBTYPE i1_type IS STD_LOGIC; +SUBTYPE i2_type IS STD_LOGIC_VECTOR(1 DOWNTO 0); +SUBTYPE i3_type IS STD_LOGIC; +-- output port types +SUBTYPE o1_type IS STD_LOGIC_VECTOR(1 DOWNTO 0); +-- output port names +CONSTANT o1_name : STRING (1 TO 7) := "ext_out"; +-- n(outputs) +CONSTANT o_num : INTEGER := 1; +-- mismatches vector type +TYPE mmvec IS ARRAY (0 to (o_num - 1)) OF INTEGER; +-- exp o/ first change track vector type +TYPE trackvec IS ARRAY (1 to o_num) OF BIT; +-- sampler type +SUBTYPE sample_type IS STD_LOGIC; +-- utility functions +FUNCTION std_logic_to_char (a: STD_LOGIC) RETURN CHARACTER; +FUNCTION std_logic_vector_to_string (a: STD_LOGIC_VECTOR) RETURN STRING; +PROCEDURE write (l:INOUT LINE; value:IN STD_LOGIC; justified: IN SIDE:= RIGHT; field:IN WIDTH:=0); +PROCEDURE write (l:INOUT LINE; value:IN STD_LOGIC_VECTOR; justified: IN SIDE:= RIGHT; field:IN WIDTH:=0); +PROCEDURE throw_error(output_port_name: IN STRING; expected_value : IN STD_LOGIC; real_value : IN STD_LOGIC); +PROCEDURE throw_error(output_port_name: IN STRING; expected_value : IN STD_LOGIC_VECTOR; real_value : IN STD_LOGIC_VECTOR); + +END marca_vhd_tb_types; + +PACKAGE BODY marca_vhd_tb_types IS + FUNCTION std_logic_to_char (a: STD_LOGIC) + RETURN CHARACTER IS + BEGIN + CASE a IS + WHEN 'U' => + RETURN 'U'; + WHEN 'X' => + RETURN 'X'; + WHEN '0' => + RETURN '0'; + WHEN '1' => + RETURN '1'; + WHEN 'Z' => + RETURN 'Z'; + WHEN 'W' => + RETURN 'W'; + WHEN 'L' => + RETURN 'L'; + WHEN 'H' => + RETURN 'H'; + WHEN '-' => + RETURN 'D'; + END CASE; + END; + + FUNCTION std_logic_vector_to_string (a: STD_LOGIC_VECTOR) + RETURN STRING IS + VARIABLE result : STRING(1 TO a'LENGTH); + VARIABLE j : NATURAL := 1; + BEGIN + FOR i IN a'RANGE LOOP + result(j) := std_logic_to_char(a(i)); + j := j + 1; + END LOOP; + RETURN result; + END; + + PROCEDURE write (l:INOUT LINE; value:IN STD_LOGIC; justified: IN SIDE:=RIGHT; field:IN WIDTH:=0) IS + BEGIN + write(L,std_logic_to_char(VALUE),JUSTIFIED,field); + END; + + PROCEDURE write (l:INOUT LINE; value:IN STD_LOGIC_VECTOR; justified: IN SIDE:= RIGHT; field:IN WIDTH:=0) IS + BEGIN + write(L,std_logic_vector_to_string(VALUE),JUSTIFIED,field); + END; + + PROCEDURE throw_error(output_port_name: IN STRING; expected_value : IN STD_LOGIC; real_value : IN STD_LOGIC) IS + VARIABLE txt : LINE; + BEGIN + write(txt,string'("ERROR! Vector Mismatch for output port ")); + write(txt,output_port_name); + write(txt,string'(" :: @time = ")); + write(txt,NOW); + write(txt,string'(", Expected value = ")); + write(txt,expected_value); + write(txt,string'(", Real value = ")); + write(txt,real_value); + writeline(output,txt); + END; + + PROCEDURE throw_error(output_port_name: IN STRING; expected_value : IN STD_LOGIC_VECTOR; real_value : IN STD_LOGIC_VECTOR) IS + VARIABLE txt : LINE; + BEGIN + write(txt,string'("ERROR! Vector Mismatch for output port ")); + write(txt,output_port_name); + write(txt,string'(" :: @time = ")); + write(txt,NOW); + write(txt,string'(", Expected value = ")); + write(txt,expected_value); + write(txt,string'(", Real value = ")); + write(txt,real_value); + writeline(output,txt); + END; + +END marca_vhd_tb_types; + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +USE WORK.marca_vhd_tb_types.ALL; + +ENTITY marca_vhd_sample_tst IS +PORT ( + s1 : IN i1_type; + s2 : IN i2_type; + s3 : IN i3_type; + sampler : OUT sample_type + ); +END marca_vhd_sample_tst; + +ARCHITECTURE sample_arch OF marca_vhd_sample_tst IS +SIGNAL clk : sample_type := '1'; +BEGIN +t_prcs_sample : PROCESS ( s1 , s2 , s3 ) +BEGIN + IF (NOW > 0 ps) AND (NOW < 850000000 ps) THEN + clk <= NOT clk ; + END IF; +END PROCESS t_prcs_sample; +sampler <= clk; +END sample_arch; + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY STD; +USE STD.textio.ALL; + +USE WORK.marca_vhd_tb_types.ALL; + +ENTITY marca_vhd_check_tst IS +GENERIC ( + debug_tbench : BIT := '0' +); +PORT ( + o1 : IN o1_type; + sampler : IN sample_type +); +END marca_vhd_check_tst; +ARCHITECTURE ovec_arch OF marca_vhd_check_tst IS +SIGNAL t_sig_o1_expected,t_sig_o1_expected_prev,t_sig_o1_prev : o1_type; + +SIGNAL trigger : BIT := '0'; +SIGNAL trigger_e : BIT := '0'; +SIGNAL trigger_r : BIT := '0'; +SIGNAL trigger_i : BIT := '0'; +SIGNAL num_mismatches : mmvec := (OTHERS => 0); + +BEGIN + +-- Update history buffers expected /o +t_prcs_update_o_expected_hist : PROCESS (trigger) +BEGIN + t_sig_o1_expected_prev <= t_sig_o1_expected; +END PROCESS t_prcs_update_o_expected_hist; + + +-- Update history buffers real /o +t_prcs_update_o_real_hist : PROCESS (trigger) +BEGIN + t_sig_o1_prev <= o1; +END PROCESS t_prcs_update_o_real_hist; + + +-- expected ext_out[1] +t_prcs_ext_out_1: PROCESS +BEGIN + t_sig_o1_expected(1) <= '0'; + WAIT FOR 93383521 ps; + t_sig_o1_expected(1) <= '1'; + WAIT FOR 100000 ps; + t_sig_o1_expected(1) <= '0'; + WAIT FOR 95600000 ps; + t_sig_o1_expected(1) <= '1'; + WAIT FOR 100000 ps; + t_sig_o1_expected(1) <= '0'; + WAIT FOR 95050000 ps; + t_sig_o1_expected(1) <= '1'; + WAIT FOR 100000 ps; + t_sig_o1_expected(1) <= '0'; + WAIT FOR 95600000 ps; + t_sig_o1_expected(1) <= '1'; + WAIT FOR 100000 ps; + t_sig_o1_expected(1) <= '0'; +WAIT; +END PROCESS t_prcs_ext_out_1; +-- expected ext_out[0] +t_prcs_ext_out_0: PROCESS +BEGIN + t_sig_o1_expected(0) <= '1'; + WAIT FOR 387433530 ps; + t_sig_o1_expected(0) <= '0'; + WAIT FOR 8800000 ps; + FOR i IN 1 TO 3 + LOOP + t_sig_o1_expected(0) <= '1'; + WAIT FOR 17600000 ps; + t_sig_o1_expected(0) <= '0'; + WAIT FOR 17600000 ps; + END LOOP; + t_sig_o1_expected(0) <= '1'; + WAIT FOR 8800000 ps; + FOR i IN 1 TO 2 + LOOP + t_sig_o1_expected(0) <= '0'; + WAIT FOR 17600000 ps; + t_sig_o1_expected(0) <= '1'; + WAIT FOR 17600000 ps; + END LOOP; + t_sig_o1_expected(0) <= '0'; + WAIT FOR 8800000 ps; + t_sig_o1_expected(0) <= '1'; + WAIT FOR 8800000 ps; + t_sig_o1_expected(0) <= '0'; + WAIT FOR 26400000 ps; + FOR i IN 1 TO 2 + LOOP + t_sig_o1_expected(0) <= '1'; + WAIT FOR 17600000 ps; + t_sig_o1_expected(0) <= '0'; + WAIT FOR 17600000 ps; + END LOOP; + t_sig_o1_expected(0) <= '1'; + WAIT FOR 8800000 ps; + t_sig_o1_expected(0) <= '0'; + WAIT FOR 8800000 ps; + t_sig_o1_expected(0) <= '1'; + WAIT FOR 8800000 ps; + t_sig_o1_expected(0) <= '0'; + WAIT FOR 35200000 ps; + t_sig_o1_expected(0) <= '1'; +WAIT; +END PROCESS t_prcs_ext_out_0; + +-- Set trigger on real/expected o/ pattern changes + +t_prcs_trigger_e : PROCESS(t_sig_o1_expected) +BEGIN + trigger_e <= NOT trigger_e; +END PROCESS t_prcs_trigger_e; + +t_prcs_trigger_r : PROCESS(o1) +BEGIN + trigger_r <= NOT trigger_r; +END PROCESS t_prcs_trigger_r; + + +t_prcs_selfcheck : PROCESS +VARIABLE i : INTEGER := 1; +VARIABLE txt : LINE; + +VARIABLE last_o1_exp : o1_type := (OTHERS => 'U'); + +VARIABLE on_first_change : trackvec := "1"; +BEGIN + +WAIT UNTIL (sampler'LAST_VALUE = '1'OR sampler'LAST_VALUE = '0') + AND sampler'EVENT; +IF (debug_tbench = '1') THEN + write(txt,string'("Scanning pattern ")); + write(txt,i); + writeline(output,txt); + write(txt,string'("| expected "));write(txt,o1_name);write(txt,string'(" = "));write(txt,t_sig_o1_expected_prev); + writeline(output,txt); + write(txt,string'("| real "));write(txt,o1_name);write(txt,string'(" = "));write(txt,t_sig_o1_prev); + writeline(output,txt); + i := i + 1; +END IF; +IF ( t_sig_o1_expected_prev /= "XX" ) AND (t_sig_o1_expected_prev /= "UU" ) AND (t_sig_o1_prev /= t_sig_o1_expected_prev) AND ( + (t_sig_o1_expected_prev /= last_o1_exp) OR + (on_first_change(1) = '1') + ) THEN + throw_error("ext_out",t_sig_o1_expected_prev,t_sig_o1_prev); + num_mismatches(0) <= num_mismatches(0) + 1; + on_first_change(1) := '0'; + last_o1_exp := t_sig_o1_expected_prev; +END IF; + trigger_i <= NOT trigger_i; +END PROCESS t_prcs_selfcheck; + + +t_prcs_trigger_res : PROCESS(trigger_e,trigger_i,trigger_r) +BEGIN + trigger <= trigger_i XOR trigger_e XOR trigger_r; +END PROCESS t_prcs_trigger_res; + +t_prcs_endsim : PROCESS +VARIABLE txt : LINE; +VARIABLE total_mismatches : INTEGER := 0; +BEGIN +WAIT FOR 850000000 ps; +total_mismatches := num_mismatches(0); +IF (total_mismatches = 0) THEN + write(txt,string'("Simulation passed !")); + writeline(output,txt); +ELSE + write(txt,total_mismatches); + write(txt,string'(" mismatched vectors : Simulation failed !")); + writeline(output,txt); +END IF; +WAIT; +END PROCESS t_prcs_endsim; + +END ovec_arch; + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY STD; +USE STD.textio.ALL; + +USE WORK.marca_vhd_tb_types.ALL; + +ENTITY marca_vhd_vec_tst IS +END marca_vhd_vec_tst; +ARCHITECTURE marca_arch OF marca_vhd_vec_tst IS +-- constants +-- signals +SIGNAL t_sig_clock : STD_LOGIC; +SIGNAL t_sig_ext_in : STD_LOGIC_VECTOR(1 DOWNTO 0); +SIGNAL t_sig_ext_out : STD_LOGIC_VECTOR(1 DOWNTO 0); +SIGNAL t_sig_ext_reset : STD_LOGIC; +SIGNAL t_sig_sampler : sample_type; + +COMPONENT marca + PORT ( + clock : IN STD_LOGIC; + ext_in : IN STD_LOGIC_VECTOR(1 DOWNTO 0); + ext_out : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); + ext_reset : IN STD_LOGIC + ); +END COMPONENT; +COMPONENT marca_vhd_check_tst +PORT ( + o1 : IN o1_type; + sampler : IN sample_type +); +END COMPONENT; +COMPONENT marca_vhd_sample_tst +PORT ( + s1 : IN i1_type; + s2 : IN i2_type; + s3 : IN i3_type; + sampler : OUT sample_type + ); +END COMPONENT; +BEGIN + i1 : marca + PORT MAP ( +-- list connections between master ports and signals + clock => t_sig_clock, + ext_in => t_sig_ext_in, + ext_out => t_sig_ext_out, + ext_reset => t_sig_ext_reset + ); + +-- clock +t_prcs_clock: PROCESS +BEGIN +LOOP + t_sig_clock <= '0'; + WAIT FOR 25000 ps; + t_sig_clock <= '1'; + WAIT FOR 25000 ps; + IF (NOW >= 850000000 ps) THEN WAIT; END IF; +END LOOP; +END PROCESS t_prcs_clock; + +-- ext_reset +t_prcs_ext_reset: PROCESS +BEGIN + t_sig_ext_reset <= '0'; + WAIT FOR 100000 ps; + t_sig_ext_reset <= '1'; +WAIT; +END PROCESS t_prcs_ext_reset; +-- ext_in[1] +t_prcs_ext_in_1: PROCESS +BEGIN + t_sig_ext_in(1) <= '0'; +WAIT; +END PROCESS t_prcs_ext_in_1; +-- ext_in[0] +t_prcs_ext_in_0: PROCESS +BEGIN + t_sig_ext_in(0) <= '1'; + WAIT FOR 8680000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 8680000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 8680000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 26040000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 8680000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 8680000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 17360000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 8680000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 8680000 ps; + t_sig_ext_in(0) <= '1'; + WAIT FOR 8680000 ps; + t_sig_ext_in(0) <= '0'; + WAIT FOR 34720000 ps; + t_sig_ext_in(0) <= '1'; +WAIT; +END PROCESS t_prcs_ext_in_0; +tb_sample : marca_vhd_sample_tst +PORT MAP ( + s1 => t_sig_clock, + s2 => t_sig_ext_in, + s3 => t_sig_ext_reset, + sampler => t_sig_sampler + ); + +tb_out : marca_vhd_check_tst +PORT MAP ( + o1 => t_sig_ext_out, + sampler => t_sig_sampler + ); +END marca_arch; Index: trunk/vhdl/code.mif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/vhdl/code.mif =================================================================== --- trunk/vhdl/code.mif (nonexistent) +++ trunk/vhdl/code.mif (revision 2)
trunk/vhdl/code.mif Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/vhdl/sc_pkg.vhd =================================================================== --- trunk/vhdl/sc_pkg.vhd (nonexistent) +++ trunk/vhdl/sc_pkg.vhd (revision 2) @@ -0,0 +1,91 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- Package SC +------------------------------------------------------------------------------- +-- definitions for the SimpCon interface +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; + +package sc_pkg is + + ----------------------------------------------------------------------------- + -- general configuration + ----------------------------------------------------------------------------- + constant SC_ADDR_WIDTH : integer := 2; + constant SC_REG_WIDTH : integer := 16; + + ----------------------------------------------------------------------------- + -- where to access SimCon modules + ----------------------------------------------------------------------------- + constant SC_MIN_ADDR : std_logic_vector := "1111111111111000"; + constant SC_MAX_ADDR : std_logic_vector := "1111111111111111"; + + ----------------------------------------------------------------------------- + -- records for simpler interfacing + ----------------------------------------------------------------------------- + type SC_IN is record + address : std_logic_vector(SC_ADDR_WIDTH-1 downto 0); + wr : std_logic; + wr_data : std_logic_vector(SC_REG_WIDTH-1 downto 0); + rd : std_logic; + end record; + + constant SC_IN_NULL : SC_IN := ((others => '0'), '0', (others => '0'), '0'); + + type SC_OUT is record + rd_data : std_logic_vector(SC_REG_WIDTH-1 downto 0); + rdy_cnt : unsigned(1 downto 0); + end record; + + constant SC_OUT_NULL : SC_OUT := ((others => '0'), "00"); + + ----------------------------------------------------------------------------- + -- output bits + ----------------------------------------------------------------------------- + constant UART_TXD : integer := 0; + constant UART_NRTS : integer := 1; + + ----------------------------------------------------------------------------- + -- input bits + ----------------------------------------------------------------------------- + constant UART_RXD : integer := 0; + constant UART_NCTS : integer := 1; + + ----------------------------------------------------------------------------- + -- interrupt numbers, >= 3 + ----------------------------------------------------------------------------- + constant UART_INTR : integer := 3; + + ----------------------------------------------------------------------------- + -- UART configuration + ----------------------------------------------------------------------------- + constant UART_BASE_ADDR : std_logic_vector(REG_WIDTH-1 downto SC_ADDR_WIDTH+1) := "1111111111111"; + constant UART_BAUD_RATE : integer := 115200; + +end sc_pkg; Index: trunk/vhdl/execute_ent.vhd =================================================================== --- trunk/vhdl/execute_ent.vhd (nonexistent) +++ trunk/vhdl/execute_ent.vhd (revision 2) @@ -0,0 +1,74 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA execution stage +------------------------------------------------------------------------------- +-- entity for the execution pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity execute is + + port ( + clock : in std_logic; + reset : in std_logic; + + busy : out std_logic; + stall : in std_logic; + + pc_in : in std_logic_vector(REG_WIDTH-1 downto 0); + pcchg : out std_logic; + pc_out : out std_logic_vector(REG_WIDTH-1 downto 0); + + dest_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + dest_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + + src1 : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + src2 : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + + aop : in ALU_OP; + mop : in MEM_OP; + iop : in INTR_OP; + + op1 : in std_logic_vector(REG_WIDTH-1 downto 0); + op2 : in std_logic_vector(REG_WIDTH-1 downto 0); + imm : in std_logic_vector(REG_WIDTH-1 downto 0); + + unit : in UNIT_SELECTOR; + target_in : in TARGET_SELECTOR; + target_out : out TARGET_SELECTOR; + + result : out std_logic_vector(REG_WIDTH-1 downto 0); + + fw_ena : in std_logic; + fw_dest : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + fw_val : in std_logic_vector(REG_WIDTH-1 downto 0); + + ext_in : in std_logic_vector(IN_BITS-1 downto 0); + ext_out : out std_logic_vector(OUT_BITS-1 downto 0)); + +end execute; Index: trunk/vhdl/writeback.vhd =================================================================== --- trunk/vhdl/writeback.vhd (nonexistent) +++ trunk/vhdl/writeback.vhd (revision 2) @@ -0,0 +1,93 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA write-back stage +------------------------------------------------------------------------------- +-- architecture of the write-back pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +architecture behaviour of writeback is + +signal pcchg_reg : std_logic; +signal pc_reg : std_logic_vector(REG_WIDTH-1 downto 0); +signal dest_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal result_reg : std_logic_vector(REG_WIDTH-1 downto 0); +signal target_reg : TARGET_SELECTOR; + +begin -- behaviour + + syn_proc: process (clock, reset) + begin -- process syn_proc + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + pcchg_reg <= '0'; + pc_reg <= (others => '0'); + dest_reg <= (others => '0'); + result_reg <= (others => '0'); + target_reg <= TARGET_NONE; + elsif clock'event and clock = '1' then -- rising clock edge + if hold = '0' then + pcchg_reg <= pcchg; + pc_reg <= pc_in; + dest_reg <= dest_in; + target_reg <= target; + result_reg <= result; + end if; + end if; + end process syn_proc; + + dispatch: process (target_reg, pcchg_reg, pc_reg, result_reg, dest_reg) + begin -- process dispatch + + pcena <= '0'; + pc_out <= pc_reg; + + ena <= '0'; + dest_out <= dest_reg; + val <= result_reg; + + case target_reg is + + when TARGET_REGISTER => + ena <= '1'; + + when TARGET_PC => + if pcchg_reg = '1' then + pcena <= '1'; + pc_out <= result_reg; + end if; + + when TARGET_BOTH => + pcena <= '1'; + ena <= '1'; + + when others => null; + end case; + + end process dispatch; + +end behaviour; Index: trunk/vhdl/intr.vhd =================================================================== --- trunk/vhdl/intr.vhd (nonexistent) +++ trunk/vhdl/intr.vhd (revision 2) @@ -0,0 +1,105 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA interrupt unit +------------------------------------------------------------------------------- +-- architecture for the interrupt unit +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; + +architecture behaviour of intr is + +type vectors is array (VEC_COUNT-1 downto 0) of std_logic_vector(REG_WIDTH-1 downto 0); +signal vecs, next_vecs : vectors; + +signal ira, next_ira : std_logic_vector(REG_WIDTH-1 downto 0); + +begin -- behaviour + + syn_proc: process (clock, reset) + begin -- process syn_proc + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + vecs <= (others => (others => '0')); + ira <= (others => '0'); + elsif clock'event and clock = '1' then -- rising clock edge + vecs <= next_vecs; + ira <= next_ira; + end if; + end process syn_proc; + + compute: process (op, a, i, pc, vecs, ira, enable, trigger) + begin -- process compute + + next_vecs <= vecs; + next_ira <= ira; + + exc <= '0'; + pcchg <= '0'; + result <= (others => '0'); + + case op is + when INTR_INTR => + if enable = '1' then + pcchg <= '1'; + result <= vecs(to_integer(unsigned(i))); + next_ira <= std_logic_vector(unsigned(pc) + 1); + end if; + when INTR_RETI => + pcchg <= '1'; + result <= ira; + when INTR_SETIRA => + next_ira <= a; + when INTR_GETIRA => + result <= ira; + when INTR_STVEC => + next_vecs(to_integer(unsigned(i))) <= a; + when INTR_LDVEC => + result <= vecs(to_integer(unsigned(i))); + when others => null; + end case; + + if enable = '1' then + for v in VEC_COUNT-1 downto 1 loop + if trigger(v) = '1' then + exc <= '1'; + pcchg <= '1'; + result <= vecs(v); + if v = EXC_ALU or v = EXC_MEM then + -- don't repeat division by zero and ill memory access + next_ira <= std_logic_vector(unsigned(pc) + 1); + else + -- repeat the instruction if interrupted + next_ira <= pc; + end if; + end if; + end loop; + end if; + + end process compute; + +end behaviour; Index: trunk/vhdl/mem.vhd =================================================================== --- trunk/vhdl/mem.vhd (nonexistent) +++ trunk/vhdl/mem.vhd (revision 2) @@ -0,0 +1,485 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA fetch stage +------------------------------------------------------------------------------- +-- architecture for the instruction-fetch pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; +use work.sc_pkg.all; + +architecture behaviour of mem is + +type WAIT_STATE is (WAIT_LOAD_EVEN, WAIT_LOAD_ODD, + WAIT_LOADL_EVEN, WAIT_LOADL_ODD, + WAIT_LOADH_EVEN, WAIT_LOADH_ODD, + WAIT_LOADB_EVEN, WAIT_LOADB_ODD, + WAIT_STORE, + WAIT_NONE); + +signal state : WAIT_STATE; +signal next_state : WAIT_STATE; + +signal old_data : std_logic_vector(REG_WIDTH-1 downto 0); +signal next_data : std_logic_vector(REG_WIDTH-1 downto 0); + +component data_memory + port ( + clken : in std_logic; + clock : in std_logic; + wren : in std_logic; + address : in std_logic_vector (ADDR_WIDTH-2 downto 0); + data : in std_logic_vector (DATA_WIDTH-1 downto 0); + q : out std_logic_vector (DATA_WIDTH-1 downto 0)); +end component; + +signal ram_enable : std_logic; + +signal wren0 : std_logic; +signal a0 : std_logic_vector(ADDR_WIDTH-2 downto 0); +signal d0 : std_logic_vector(DATA_WIDTH-1 downto 0); +signal q0 : std_logic_vector(DATA_WIDTH-1 downto 0); + +signal wren1 : std_logic; +signal a1 : std_logic_vector(ADDR_WIDTH-2 downto 0); +signal d1 : std_logic_vector(DATA_WIDTH-1 downto 0); +signal q1 : std_logic_vector(DATA_WIDTH-1 downto 0); + +component data_rom + generic ( + init_file : string); + port ( + clken : in std_logic; + clock : in std_logic; + address : in std_logic_vector (RADDR_WIDTH-2 downto 0); + q : out std_logic_vector (RDATA_WIDTH-1 downto 0)); +end component; + +signal rom_enable : std_logic; + +signal ra0 : std_logic_vector(RADDR_WIDTH-2 downto 0); +signal rq0 : std_logic_vector(RDATA_WIDTH-1 downto 0); + +signal ra1 : std_logic_vector(RADDR_WIDTH-2 downto 0); +signal rq1 : std_logic_vector(RDATA_WIDTH-1 downto 0); + + +signal sc_input : SC_IN; +signal sc_output : SC_OUT; + +component sc_uart + generic ( + clock_freq : integer; + baud_rate : integer; + txf_depth : integer; txf_thres : integer; + rxf_depth : integer; rxf_thres : integer); + port ( + clock : in std_logic; + reset : in std_logic; + input : in SC_IN; + output : out SC_OUT; + intr : out std_logic; + txd : out std_logic; + rxd : in std_logic; + nrts : out std_logic; + ncts : in std_logic); +end component; + +signal uart_input : SC_IN; +signal uart_output : SC_OUT; + +begin -- behaviour + + intrs(VEC_COUNT-1 downto 4) <= (others => '0'); + + data_memory_0_unit : data_memory + port map ( + clken => ram_enable, + clock => clock, + wren => wren0, + address => a0, + data => d0, + q => q0); + + data_memory_1_unit : data_memory + port map ( + clken => ram_enable, + clock => clock, + wren => wren1, + address => a1, + data => d1, + q => q1); + + data_rom_0_unit : data_rom + generic map ( + init_file => "../vhdl/rom0.mif") + port map ( + clken => rom_enable, + clock => clock, + address => ra0, + q => rq0); + + data_rom_1_unit : data_rom + generic map ( + init_file => "../vhdl/rom1.mif") + port map ( + clken => rom_enable, + clock => clock, + address => ra1, + q => rq1); + + uart_unit : sc_uart + generic map ( + clock_freq => CLOCK_FREQ, + baud_rate => UART_BAUD_RATE, + txf_depth => 2, txf_thres => 1, + rxf_depth => 2, rxf_thres => 1) + port map ( + clock => clock, + reset => reset, + input => uart_input, + output => uart_output, + intr => intrs(UART_INTR), + txd => ext_out(UART_TXD), + rxd => ext_in(UART_RXD), + nrts => ext_out(UART_NRTS), + ncts => ext_in(UART_NCTS)); + + syn_proc: process (clock, reset) + begin -- process syn_proc + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + state <= WAIT_NONE; + old_data <= (others => '0'); + elsif clock'event and clock = '1' then -- rising clock edge + state <= next_state; + old_data <= next_data; + end if; + end process syn_proc; + + business: process (next_state) + begin -- process business + if next_state /= WAIT_NONE then + busy <= '1'; + else + busy <= '0'; + end if; + end process business; + + sc_mux: process (address, sc_input, + uart_output) + begin -- process sc_mux + + uart_input <= SC_IN_NULL; + sc_output <= SC_OUT_NULL; + + case address(REG_WIDTH-1 downto SC_ADDR_WIDTH+1) is + when UART_BASE_ADDR => + uart_input <= sc_input; + sc_output <= uart_output; + when others => null; + end case; + + end process sc_mux; + + readwrite: process (state, op, address, data, old_data, q0, q1, rq0, rq1, sc_output) + begin -- process readwrite + exc <= '0'; + + ram_enable <= '0'; + + wren0 <= '0'; + wren1 <= '0'; + + a0 <= (others => '0'); + d0 <= (others => '0'); + + a1 <= (others => '0'); + d1 <= (others => '0'); + + rom_enable <= '0'; + + ra0 <= (others => '0'); + ra1 <= (others => '0'); + + sc_input <= SC_IN_NULL; + + result <= (others => '0'); + + next_state <= WAIT_NONE; + next_data <= data; + + if unsigned(address) >= unsigned(MEM_MIN_ADDR) + and unsigned(address) <= unsigned(MEM_MAX_ADDR) then + + -- regular memory access + if op /= MEM_NOP then + ram_enable <= '1'; + end if; + + case state is + when WAIT_LOAD_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= q1; + result(REG_WIDTH/2-1 downto 0) <= q0; + next_state <= WAIT_NONE; + + when WAIT_LOAD_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= q0; + result(REG_WIDTH/2-1 downto 0) <= q1; + next_state <= WAIT_NONE; + + when WAIT_LOADL_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= old_data(REG_WIDTH-1 downto REG_WIDTH/2); + result(REG_WIDTH/2-1 downto 0) <= q0; + next_state <= WAIT_NONE; + + when WAIT_LOADL_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= old_data(REG_WIDTH-1 downto REG_WIDTH/2); + result(REG_WIDTH/2-1 downto 0) <= q1; + next_state <= WAIT_NONE; + + when WAIT_LOADH_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= q0; + result(REG_WIDTH/2-1 downto 0) <= old_data(REG_WIDTH/2-1 downto 0); + next_state <= WAIT_NONE; + + when WAIT_LOADH_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= q1; + result(REG_WIDTH/2-1 downto 0) <= old_data(REG_WIDTH/2-1 downto 0); + next_state <= WAIT_NONE; + + when WAIT_LOADB_EVEN => result <= std_logic_vector(resize(signed(q0), REG_WIDTH)); + next_state <= WAIT_NONE; + + when WAIT_LOADB_ODD => result <= std_logic_vector(resize(signed(q1), REG_WIDTH)); + next_state <= WAIT_NONE; + + when WAIT_NONE => + case op is + when MEM_LOAD => if address(0) = '0' then + a0 <= address(ADDR_WIDTH-1 downto 1); + a1 <= address(ADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOAD_EVEN; + else + a1 <= address(ADDR_WIDTH-1 downto 1); + a0 <= std_logic_vector(unsigned(address(ADDR_WIDTH-1 downto 1)) + 1); + next_state <= WAIT_LOAD_ODD; + end if; + when MEM_LOADL => if address(0) = '0' then + a0 <= address(ADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADL_EVEN; + else + a1 <= address(ADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADL_ODD; + end if; + when MEM_LOADH => if address(0) = '0' then + a0 <= address(ADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADH_EVEN; + else + a1 <= address(ADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADH_ODD; + end if; + when MEM_LOADB => if address(0) = '0' then + a0 <= address(ADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADB_EVEN; + else + a1 <= address(ADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADB_ODD; + end if; + when MEM_STORE => if address(0) = '0' then + wren0 <= '1'; + wren1 <= '1'; + a0 <= address(ADDR_WIDTH-1 downto 1); + a1 <= address(ADDR_WIDTH-1 downto 1); + d0 <= data(REG_WIDTH/2-1 downto 0); + d1 <= data(REG_WIDTH-1 downto REG_WIDTH/2); + next_state <= WAIT_NONE; + else + wren0 <= '1'; + wren1 <= '1'; + a1 <= address(ADDR_WIDTH-1 downto 1); + a0 <= std_logic_vector(unsigned(address(ADDR_WIDTH-1 downto 1)) + 1); + d1 <= data(REG_WIDTH/2-1 downto 0); + d0 <= data(REG_WIDTH-1 downto REG_WIDTH/2); + next_state <= WAIT_NONE; + end if; + when MEM_STOREL => if address(0) = '0' then + wren0 <= '1'; + a0 <= address(ADDR_WIDTH-1 downto 1); + d0 <= data(REG_WIDTH/2-1 downto 0); + next_state <= WAIT_NONE; + else + wren1 <= '1'; + a1 <= address(ADDR_WIDTH-1 downto 1); + d1 <= data(REG_WIDTH/2-1 downto 0); + next_state <= WAIT_NONE; + end if; + when MEM_STOREH => if address(0) = '0' then + wren0 <= '1'; + a0 <= address(ADDR_WIDTH-1 downto 1); + d0 <= data(REG_WIDTH-1 downto REG_WIDTH/2); + next_state <= WAIT_NONE; + else + wren1 <= '1'; + a1 <= address(ADDR_WIDTH-1 downto 1); + d1 <= data(REG_WIDTH-1 downto REG_WIDTH/2); + next_state <= WAIT_NONE; + end if; + when MEM_NOP => next_state <= WAIT_NONE; + when others => null; + end case; + when others => null; + end case; + + elsif unsigned(address) >= unsigned(ROM_MIN_ADDR) + and unsigned(address) <= unsigned(ROM_MAX_ADDR) then + + -- accessing the ROM + if op /= MEM_NOP then + rom_enable <= '1'; + end if; + + case state is + when WAIT_LOAD_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= rq1; + result(REG_WIDTH/2-1 downto 0) <= rq0; + next_state <= WAIT_NONE; + + when WAIT_LOAD_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= rq0; + result(REG_WIDTH/2-1 downto 0) <= rq1; + next_state <= WAIT_NONE; + + when WAIT_LOADL_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= old_data(REG_WIDTH-1 downto REG_WIDTH/2); + result(REG_WIDTH/2-1 downto 0) <= rq0; + next_state <= WAIT_NONE; + + when WAIT_LOADL_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= old_data(REG_WIDTH-1 downto REG_WIDTH/2); + result(REG_WIDTH/2-1 downto 0) <= rq1; + next_state <= WAIT_NONE; + + when WAIT_LOADH_EVEN => result(REG_WIDTH-1 downto REG_WIDTH/2) <= rq0; + result(REG_WIDTH/2-1 downto 0) <= old_data(REG_WIDTH/2-1 downto 0); + next_state <= WAIT_NONE; + + when WAIT_LOADH_ODD => result(REG_WIDTH-1 downto REG_WIDTH/2) <= rq1; + result(REG_WIDTH/2-1 downto 0) <= old_data(REG_WIDTH/2-1 downto 0); + next_state <= WAIT_NONE; + + when WAIT_LOADB_EVEN => result <= std_logic_vector(resize(signed(rq0), REG_WIDTH)); + next_state <= WAIT_NONE; + + when WAIT_LOADB_ODD => result <= std_logic_vector(resize(signed(rq1), REG_WIDTH)); + next_state <= WAIT_NONE; + + when WAIT_NONE => + case op is + when MEM_LOAD => if address(0) = '0' then + ra0 <= address(RADDR_WIDTH-1 downto 1); + ra1 <= address(RADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOAD_EVEN; + else + ra1 <= address(RADDR_WIDTH-1 downto 1); + ra0 <= std_logic_vector(unsigned(address(RADDR_WIDTH-1 downto 1)) + 1); + next_state <= WAIT_LOAD_ODD; + end if; + when MEM_LOADL => if address(0) = '0' then + ra0 <= address(RADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADL_EVEN; + else + ra1 <= address(RADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADL_ODD; + end if; + when MEM_LOADH => if address(0) = '0' then + ra0 <= address(RADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADH_EVEN; + else + ra1 <= address(RADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADH_ODD; + end if; + when MEM_LOADB => if address(0) = '0' then + ra0 <= address(RADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADB_EVEN; + else + ra1 <= address(RADDR_WIDTH-1 downto 1); + next_state <= WAIT_LOADB_ODD; + end if; + when MEM_NOP => next_state <= WAIT_NONE; + when others => exc <= '1'; -- inhibit invalid operations + end case; + when others => null; + end case; + + elsif unsigned(address) >= unsigned(SC_MIN_ADDR) + and unsigned(address) <= unsigned(SC_MAX_ADDR) + and address(0) = '0' then + + -- access via SimpCon interface + case state is + + when WAIT_LOAD_EVEN => + if sc_output.rdy_cnt /= "00" then + next_state <= WAIT_LOAD_EVEN; + else + result <= sc_output.rd_data; + next_state <= WAIT_NONE; + end if; + + when WAIT_STORE => + if sc_output.rdy_cnt /= "00" then + next_state <= WAIT_STORE; + else + next_state <= WAIT_NONE; + end if; + + when WAIT_NONE => + case op is + + when MEM_LOAD => + sc_input.address <= address(SC_ADDR_WIDTH downto 1); + sc_input.wr <= '0'; + sc_input.wr_data <= (others => '0'); + sc_input.rd <= '1'; + next_state <= WAIT_LOAD_EVEN; + + when MEM_STORE => + sc_input.address <= address(SC_ADDR_WIDTH downto 1); + sc_input.wr <= '1'; + sc_input.wr_data <= data; + sc_input.rd <= '0'; + next_state <= WAIT_STORE; + + when MEM_NOP => next_state <= WAIT_NONE; + + when others => exc <= '1'; -- inhibit invalid operations + + end case; + when others => null; + end case; + + else + -- invalid address and/or alignment + if op /= MEM_NOP then + exc <= '1'; + end if; + end if; + + end process readwrite; + +end behaviour; Index: trunk/vhdl/data_rom.bsf =================================================================== --- trunk/vhdl/data_rom.bsf (nonexistent) +++ trunk/vhdl/data_rom.bsf (revision 2) @@ -0,0 +1,74 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2006 Altera Corporation +Your use of Altera Corporation's design tools, logic functions +and other software and tools, and its AMPP partner logic +functions, and any output files any of the foregoing +(including device programming or simulation files), and any +associated documentation or information are expressly subject +to the terms and conditions of the Altera Program License +Subscription Agreement, Altera MegaCore Function License +Agreement, or other applicable license agreement, including, +without limitation, that your use is for the sole purpose of +programming logic devices manufactured by Altera and sold by +Altera or its authorized distributors. Please refer to the +applicable agreement for further details. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 216 152) + (text "data_rom" (rect 81 1 144 17)(font "Arial" (font_size 10))) + (text "inst" (rect 8 136 25 148)(font "Arial" )) + (port + (pt 0 32) + (input) + (text "address[6..0]" (rect 0 0 75 14)(font "Arial" (font_size 8))) + (text "address[6..0]" (rect 4 19 63 32)(font "Arial" (font_size 8))) + (line (pt 0 32)(pt 88 32)(line_width 3)) + ) + (port + (pt 0 112) + (input) + (text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8))) + (text "clock" (rect 4 99 29 112)(font "Arial" (font_size 8))) + (line (pt 0 112)(pt 80 112)(line_width 1)) + ) + (port + (pt 0 128) + (input) + (text "clken" (rect 0 0 29 14)(font "Arial" (font_size 8))) + (text "clken" (rect 4 115 29 128)(font "Arial" (font_size 8))) + (line (pt 0 128)(pt 16 128)(line_width 1)) + ) + (port + (pt 216 32) + (output) + (text "q[7..0]" (rect 0 0 35 14)(font "Arial" (font_size 8))) + (text "q[7..0]" (rect 183 19 213 32)(font "Arial" (font_size 8))) + (line (pt 216 32)(pt 136 32)(line_width 3)) + ) + (drawing + (text "8 bits" (rect 108 48 120 71)(font "Arial" )(vertical)) + (text "128 words" (rect 121 39 133 81)(font "Arial" )(vertical)) + (text "Block type: AUTO" (rect 41 132 117 144)(font "Arial" )) + (line (pt 104 24)(pt 136 24)(line_width 1)) + (line (pt 136 24)(pt 136 96)(line_width 1)) + (line (pt 136 96)(pt 104 96)(line_width 1)) + (line (pt 104 96)(pt 104 24)(line_width 1)) + (line (pt 118 58)(pt 123 63)(line_width 1)) + (line (pt 118 62)(pt 123 57)(line_width 1)) + (line (pt 88 27)(pt 96 27)(line_width 1)) + (line (pt 96 27)(pt 96 39)(line_width 1)) + (line (pt 96 39)(pt 88 39)(line_width 1)) + (line (pt 88 39)(pt 88 27)(line_width 1)) + (line (pt 88 34)(pt 90 36)(line_width 1)) + (line (pt 90 36)(pt 88 38)(line_width 1)) + (line (pt 80 36)(pt 88 36)(line_width 1)) + (line (pt 96 32)(pt 104 32)(line_width 3)) + (line (pt 80 112)(pt 80 36)(line_width 1)) + ) +) Index: trunk/vhdl/writeback_ent.vhd =================================================================== --- trunk/vhdl/writeback_ent.vhd (nonexistent) +++ trunk/vhdl/writeback_ent.vhd (revision 2) @@ -0,0 +1,58 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA write-back stage +------------------------------------------------------------------------------- +-- entity for the write-back pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity writeback is + + port ( + clock : in std_logic; + reset : in std_logic; + + hold : in std_logic; + + pc_in : in std_logic_vector(REG_WIDTH-1 downto 0); + pcchg : in std_logic; + pc_out : out std_logic_vector(REG_WIDTH-1 downto 0); + + pcena : out std_logic; + + dest_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + dest_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + + target : in TARGET_SELECTOR; + result : in std_logic_vector(REG_WIDTH-1 downto 0); + + ena : out std_logic; + val : out std_logic_vector(REG_WIDTH-1 downto 0) + ); + +end writeback; Index: trunk/vhdl/intr_ent.vhd =================================================================== --- trunk/vhdl/intr_ent.vhd (nonexistent) +++ trunk/vhdl/intr_ent.vhd (revision 2) @@ -0,0 +1,52 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA interrupt unit +------------------------------------------------------------------------------- +-- entity for the interrupt unit +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity intr is + + port ( + clock : in std_logic; + reset : in std_logic; + enable : in std_logic; + + trigger : in std_logic_vector(VEC_COUNT-1 downto 1); + + op : in INTR_OP; + a : in std_logic_vector(REG_WIDTH-1 downto 0); + i : in std_logic_vector(REG_WIDTH-1 downto 0); + pc : in std_logic_vector(REG_WIDTH-1 downto 0); + + exc : out std_logic; + pcchg : out std_logic; + result : out std_logic_vector(REG_WIDTH-1 downto 0)); + +end intr; Index: trunk/vhdl/fifo.vhd =================================================================== --- trunk/vhdl/fifo.vhd (nonexistent) +++ trunk/vhdl/fifo.vhd (revision 2) @@ -0,0 +1,155 @@ +-- +-- fifo.vhd +-- +-- simple fifo +-- +-- uses FF and every rd or wr has to 'bubble' through the hole fifo. +-- +-- Author: Martin Schoeberl martin.schoeberl@chello.at +-- +-- +-- resources on ACEX1K +-- +-- (width+2)*depth-1 LCs +-- +-- +-- 2002-01-06 first working version +-- 2002-11-03 a signal for reaching threshold +-- 2005-02-20 change entity order for modelsim vcom +-- + +library ieee; +use ieee.std_logic_1164.all; + +use work.marca_pkg.all; + +entity fifo_elem is + + generic (width : integer); + port ( + clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + rd_prev : out std_logic; + full : out std_logic + ); +end fifo_elem; + +architecture rtl of fifo_elem is + + signal buf : std_logic_vector(width-1 downto 0); + signal f : std_logic; + +begin + + dout <= buf; + + process(clk, reset, f) + + begin + + full <= f; + + if reset = RESET_ACTIVE then + + buf <= (others => '0'); + f <= '0'; + rd_prev <= '0'; + + elsif rising_edge(clk) then + + rd_prev <= '0'; + if f='0' then + if wr='1' then + rd_prev <= '1'; + buf <= din; + f <= '1'; + end if; + else + if rd='1' then + f <= '0'; + end if; + end if; + + end if; + + end process; + +end rtl; + +library ieee; +use ieee.std_logic_1164.all; + +entity fifo is + + generic (width : integer := 8; depth : integer := 4; thres : integer := 2); + port ( + clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + empty : out std_logic; + full : out std_logic; + half : out std_logic + ); +end fifo ; + +architecture rtl of fifo is + + component fifo_elem is + generic (width : integer); + port ( + clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + rd_prev : out std_logic; + full : out std_logic); + end component; + + signal r, w, rp, f : std_logic_vector(depth-1 downto 0); + type d_array is array (0 to depth-1) of std_logic_vector(width-1 downto 0); + signal di, do : d_array; + +begin + + g1: for i in 0 to depth-1 generate + + f1: fifo_elem generic map (width) + port map (clk, reset, di(i), do(i), r(i), w(i), rp(i), f(i)); + + x: if i '0'); + reg_operand2 <= (others => '0'); + reg_product <= (others => '0'); + reg_hotbit <= (others => '0'); + reg_hotbit(0) <= '1'; + + elsif clock'event and clock = '1' then -- rising clock edge + + if trigger = '1' then + reg_operand1 <= operand1; + reg_operand2 <= operand2; + reg_product <= (others => '0'); + reg_hotbit(width-1) <= '1'; + reg_hotbit(width-2 downto 0) <= (others => '0'); + reg_busy <= '1'; + else + reg_operand1 <= next_operand1; + reg_operand2 <= next_operand2; + reg_product(width-1 downto 0) <= next_product(width-1 downto 0); + -- sticky "carry"-bit + reg_product(width) <= reg_product(width) or next_product(width); + reg_hotbit <= next_hotbit; + reg_busy <= next_busy; + end if; + + end if; + end process syn_proc; + + compute: process (reg_operand1, reg_operand2, reg_product, reg_hotbit) + begin -- process compute + + next_operand1 <= reg_operand1(width-2 downto 0) & '0'; + next_operand2 <= '0' & reg_operand2(width-1 downto 1); + next_hotbit <= '0' & reg_hotbit(width-1 downto 1); + + if reg_hotbit(0) = '1' then + next_hotbit <= reg_hotbit; + next_busy <= '0'; + else + next_busy <= '1'; + end if; + + if reg_operand2(0) = '1' then + next_product <= std_logic_vector(unsigned(reg_product) + unsigned(reg_operand1(width-1 downto 0))); + else + next_product <= reg_product; + end if; + + end process compute; + +end behaviour; Index: trunk/vhdl/uart_reverse.s =================================================================== --- trunk/vhdl/uart_reverse.s (nonexistent) +++ trunk/vhdl/uart_reverse.s (revision 2) @@ -0,0 +1,79 @@ +.data + data 0x0A + data 0x0D +buffer: + +.text +;;; initialization + ldib r0, -8 ; config/status + ldib r1, -6 ; data + + ldil r2, lo(buffer) ; buffer address + ldih r2, hi(buffer) ; buffer address + + ldib r3, 0x0A ; newline character + ldib r4, 0x0D ; carriage return + + ldib r5, 0 ; mode + + ldib r7, isr ; register isr + stvec r7, 3 + + ldib r7, (1 << 3) ; enable receive interrupts + store r7, r0 + + sei ; enable interrupts + +;;; loop forever +loop: br loop + + +;;; ISR +isr: + cmpi r5, 0 ; check mode + brnz write_mode + +;;; reading +read_mode: + load r7, r1 ; read data + + cmp r7, r3 ; change mode upon newline + brnz read_CR + + ldib r7, (1 << 2) ; do the change + store r7, r0 + ldib r5, 1 + reti + +read_CR: + cmp r7, r4 ; ignore carriage return + brnz read_cont + reti + +read_cont: + storel r7, r2 ; store date + addi r2, 1 + reti + +;;; writing +write_mode: + addi r2, -1 + + cmpi r2, -1 ; change mode if there is no more data + brnz write_cont + + ldil r2, lo(buffer) ; correct pointer to buffer + ldih r2, hi(buffer) + + ldib r7, (1 << 3) ; do the change + store r7, r0 + ldib r5, 0 + reti + +write_cont: + loadl r7, r2 ; write data + store r7, r1 + reti + + + Index: trunk/vhdl/data_memory.bsf =================================================================== --- trunk/vhdl/data_memory.bsf (nonexistent) +++ trunk/vhdl/data_memory.bsf (revision 2) @@ -0,0 +1,104 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2006 Altera Corporation +Your use of Altera Corporation's design tools, logic functions +and other software and tools, and its AMPP partner logic +functions, and any output files any of the foregoing +(including device programming or simulation files), and any +associated documentation or information are expressly subject +to the terms and conditions of the Altera Program License +Subscription Agreement, Altera MegaCore Function License +Agreement, or other applicable license agreement, including, +without limitation, that your use is for the sole purpose of +programming logic devices manufactured by Altera and sold by +Altera or its authorized distributors. Please refer to the +applicable agreement for further details. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 216 152) + (text "data_memory" (rect 69 1 162 17)(font "Arial" (font_size 10))) + (text "inst" (rect 8 136 25 148)(font "Arial" )) + (port + (pt 0 32) + (input) + (text "data[7..0]" (rect 0 0 53 14)(font "Arial" (font_size 8))) + (text "data[7..0]" (rect 4 19 49 32)(font "Arial" (font_size 8))) + (line (pt 0 32)(pt 88 32)(line_width 3)) + ) + (port + (pt 0 48) + (input) + (text "wren" (rect 0 0 30 14)(font "Arial" (font_size 8))) + (text "wren" (rect 4 35 26 48)(font "Arial" (font_size 8))) + (line (pt 0 48)(pt 88 48)(line_width 1)) + ) + (port + (pt 0 64) + (input) + (text "address[11..0]" (rect 0 0 82 14)(font "Arial" (font_size 8))) + (text "address[11..0]" (rect 4 51 69 64)(font "Arial" (font_size 8))) + (line (pt 0 64)(pt 88 64)(line_width 3)) + ) + (port + (pt 0 112) + (input) + (text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8))) + (text "clock" (rect 4 99 29 112)(font "Arial" (font_size 8))) + (line (pt 0 112)(pt 80 112)(line_width 1)) + ) + (port + (pt 0 128) + (input) + (text "clken" (rect 0 0 29 14)(font "Arial" (font_size 8))) + (text "clken" (rect 4 115 29 128)(font "Arial" (font_size 8))) + (line (pt 0 128)(pt 16 128)(line_width 1)) + ) + (port + (pt 216 32) + (output) + (text "q[7..0]" (rect 0 0 35 14)(font "Arial" (font_size 8))) + (text "q[7..0]" (rect 183 19 213 32)(font "Arial" (font_size 8))) + (line (pt 216 32)(pt 136 32)(line_width 3)) + ) + (drawing + (text "8 bits" (rect 108 48 120 71)(font "Arial" )(vertical)) + (text "4096 words" (rect 121 36 133 83)(font "Arial" )(vertical)) + (text "Block type: AUTO" (rect 41 132 117 144)(font "Arial" )) + (line (pt 104 24)(pt 136 24)(line_width 1)) + (line (pt 136 24)(pt 136 96)(line_width 1)) + (line (pt 136 96)(pt 104 96)(line_width 1)) + (line (pt 104 96)(pt 104 24)(line_width 1)) + (line (pt 118 58)(pt 123 63)(line_width 1)) + (line (pt 118 62)(pt 123 57)(line_width 1)) + (line (pt 88 27)(pt 96 27)(line_width 1)) + (line (pt 96 27)(pt 96 39)(line_width 1)) + (line (pt 96 39)(pt 88 39)(line_width 1)) + (line (pt 88 39)(pt 88 27)(line_width 1)) + (line (pt 88 34)(pt 90 36)(line_width 1)) + (line (pt 90 36)(pt 88 38)(line_width 1)) + (line (pt 80 36)(pt 88 36)(line_width 1)) + (line (pt 96 32)(pt 104 32)(line_width 3)) + (line (pt 88 43)(pt 96 43)(line_width 1)) + (line (pt 96 43)(pt 96 55)(line_width 1)) + (line (pt 96 55)(pt 88 55)(line_width 1)) + (line (pt 88 55)(pt 88 43)(line_width 1)) + (line (pt 88 50)(pt 90 52)(line_width 1)) + (line (pt 90 52)(pt 88 54)(line_width 1)) + (line (pt 80 52)(pt 88 52)(line_width 1)) + (line (pt 96 48)(pt 104 48)(line_width 1)) + (line (pt 88 59)(pt 96 59)(line_width 1)) + (line (pt 96 59)(pt 96 71)(line_width 1)) + (line (pt 96 71)(pt 88 71)(line_width 1)) + (line (pt 88 71)(pt 88 59)(line_width 1)) + (line (pt 88 66)(pt 90 68)(line_width 1)) + (line (pt 90 68)(pt 88 70)(line_width 1)) + (line (pt 80 68)(pt 88 68)(line_width 1)) + (line (pt 96 64)(pt 104 64)(line_width 3)) + (line (pt 80 112)(pt 80 36)(line_width 1)) + ) +) Index: trunk/vhdl/code_memory.bsf =================================================================== --- trunk/vhdl/code_memory.bsf (nonexistent) +++ trunk/vhdl/code_memory.bsf (revision 2) @@ -0,0 +1,74 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2006 Altera Corporation +Your use of Altera Corporation's design tools, logic functions +and other software and tools, and its AMPP partner logic +functions, and any output files any of the foregoing +(including device programming or simulation files), and any +associated documentation or information are expressly subject +to the terms and conditions of the Altera Program License +Subscription Agreement, Altera MegaCore Function License +Agreement, or other applicable license agreement, including, +without limitation, that your use is for the sole purpose of +programming logic devices manufactured by Altera and sold by +Altera or its authorized distributors. Please refer to the +applicable agreement for further details. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 216 152) + (text "code_memory" (rect 67 1 163 17)(font "Arial" (font_size 10))) + (text "inst" (rect 8 136 25 148)(font "Arial" )) + (port + (pt 0 32) + (input) + (text "address[11..0]" (rect 0 0 82 14)(font "Arial" (font_size 8))) + (text "address[11..0]" (rect 4 19 69 32)(font "Arial" (font_size 8))) + (line (pt 0 32)(pt 88 32)(line_width 3)) + ) + (port + (pt 0 112) + (input) + (text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8))) + (text "clock" (rect 4 99 29 112)(font "Arial" (font_size 8))) + (line (pt 0 112)(pt 80 112)(line_width 1)) + ) + (port + (pt 0 128) + (input) + (text "clken" (rect 0 0 29 14)(font "Arial" (font_size 8))) + (text "clken" (rect 4 115 29 128)(font "Arial" (font_size 8))) + (line (pt 0 128)(pt 16 128)(line_width 1)) + ) + (port + (pt 216 32) + (output) + (text "q[15..0]" (rect 0 0 42 14)(font "Arial" (font_size 8))) + (text "q[15..0]" (rect 177 19 213 32)(font "Arial" (font_size 8))) + (line (pt 216 32)(pt 136 32)(line_width 3)) + ) + (drawing + (text "16 bits" (rect 108 46 120 74)(font "Arial" )(vertical)) + (text "4096 words" (rect 121 36 133 83)(font "Arial" )(vertical)) + (text "Block type: AUTO" (rect 41 132 117 144)(font "Arial" )) + (line (pt 104 24)(pt 136 24)(line_width 1)) + (line (pt 136 24)(pt 136 96)(line_width 1)) + (line (pt 136 96)(pt 104 96)(line_width 1)) + (line (pt 104 96)(pt 104 24)(line_width 1)) + (line (pt 118 58)(pt 123 63)(line_width 1)) + (line (pt 118 62)(pt 123 57)(line_width 1)) + (line (pt 88 27)(pt 96 27)(line_width 1)) + (line (pt 96 27)(pt 96 39)(line_width 1)) + (line (pt 96 39)(pt 88 39)(line_width 1)) + (line (pt 88 39)(pt 88 27)(line_width 1)) + (line (pt 88 34)(pt 90 36)(line_width 1)) + (line (pt 90 36)(pt 88 38)(line_width 1)) + (line (pt 80 36)(pt 88 36)(line_width 1)) + (line (pt 96 32)(pt 104 32)(line_width 3)) + (line (pt 80 112)(pt 80 36)(line_width 1)) + ) +) Index: trunk/vhdl/multiplier_ent.vhd =================================================================== --- trunk/vhdl/multiplier_ent.vhd (nonexistent) +++ trunk/vhdl/multiplier_ent.vhd (revision 2) @@ -0,0 +1,48 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA multiplier +------------------------------------------------------------------------------- +-- entity of a bit-serial multiplier +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity multiplier is + + generic ( + width : integer := REG_WIDTH); + + port ( + clock : in std_logic; + reset : in std_logic; + trigger : in std_logic; + operand1 : in std_logic_vector(width-1 downto 0); + operand2 : in std_logic_vector(width-1 downto 0); + busy : out std_logic; + product : out std_logic_vector(width downto 0)); + +end multiplier; Index: trunk/vhdl/Makefile =================================================================== --- trunk/vhdl/Makefile (nonexistent) +++ trunk/vhdl/Makefile (revision 2) @@ -0,0 +1,2 @@ +program: factorial.s + ../../spar/as1 --output=code.mif --rom0file=rom0.mif --rom1file=rom1.mif factorial.s Index: trunk/vhdl/sc_uart.vhd =================================================================== --- trunk/vhdl/sc_uart.vhd (nonexistent) +++ trunk/vhdl/sc_uart.vhd (revision 2) @@ -0,0 +1,367 @@ +-- +-- sc_uart.vhd +-- +-- 8-N-1 serial interface +-- +-- wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on ACEX1K30-3 +-- +-- 100 LCs, max 90 MHz +-- +-- resetting rts with fifo_full-1 works with C program on pc +-- but not with javax.comm: sends some more bytes after deassert +-- of rts (16 byte blocks regardless of rts). +-- Try to stop with half full fifo. +-- +-- todo: +-- +-- +-- 2000-12-02 first working version +-- 2002-01-06 changed tdr and rdr to fifos. +-- 2002-05-15 changed clkdiv calculation +-- 2002-11-01 don't wait if read fifo is full, just drop the byte +-- 2002-11-03 use threshold in fifo to reset rts +-- don't send if cts is '0' +-- 2002-11-08 rx fifo to 20 characters and stop after 4 +-- 2003-07-05 new IO standard, change cts/rts to neg logic +-- 2003-09-19 sync ncts in! +-- 2004-03-23 two stop bits +-- 2005-11-30 change interface to SimpCon +-- 2006-08-07 rxd input register with clk to avoid Quartus tsu violation +-- 2006-08-13 use 3 FFs for the rxd input at clk +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.marca_pkg.all; +use work.sc_pkg.all; + +entity sc_uart is + + generic (clock_freq : integer; + baud_rate : integer; + txf_depth : integer; txf_thres : integer; + rxf_depth : integer; rxf_thres : integer); + + port (clock : in std_logic; + reset : in std_logic; + +-- SimpCon interface + input : in SC_IN; + output : out SC_OUT; + + intr : out std_logic; + + txd : out std_logic; + rxd : in std_logic; + ncts : in std_logic; + nrts : out std_logic); + +end sc_uart; + +architecture rtl of sc_uart is + + component fifo is + + generic (width : integer; + depth : integer; + thres : integer); + + port (clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + empty : out std_logic; + full : out std_logic; + half : out std_logic); + end component; + +-- +-- signals for uart connection +-- + signal ua_dout : std_logic_vector(7 downto 0); + signal ua_wr, tdre : std_logic; + signal ua_rd, rdrf : std_logic; + + type uart_tx_state_type is (s0, s1); + signal uart_tx_state : uart_tx_state_type; + + signal tf_dout : std_logic_vector(7 downto 0); -- fifo out + signal tf_rd : std_logic; + signal tf_empty : std_logic; + signal tf_full : std_logic; + signal tf_half : std_logic; + + signal ncts_buf : std_logic_vector(2 downto 0); -- sync in + signal tsr : std_logic_vector(9 downto 0); -- tx shift register + signal tx_clk : std_logic; + + type uart_rx_state_type is (s0, s1, s2); + signal uart_rx_state : uart_rx_state_type; + + signal rf_wr : std_logic; + signal rf_empty : std_logic; + signal rf_full : std_logic; + signal rf_half : std_logic; + + signal rxd_reg : std_logic_vector(2 downto 0); + signal rx_buf : std_logic_vector(2 downto 0); -- sync in, filter + signal rx_d : std_logic; -- rx serial data + signal rsr : std_logic_vector(9 downto 0); -- rx shift register + signal rx_clk : std_logic; + signal rx_clk_ena : std_logic; + + signal rdrf_iena : std_logic; + signal tdre_iena : std_logic; + + constant clk16_cnt : integer := (clock_freq/baud_rate+8)/16-1; + +begin + + output.rdy_cnt <= "00"; -- no wait states + output.rd_data(SC_REG_WIDTH-1 downto 8) <= std_logic_vector(to_unsigned(0, SC_REG_WIDTH-8)); + +-- +-- The registered MUX is all we need for a SimpCon read. +-- The read data is stored in registered rd_data. +-- + process(clock, reset) + begin + + if reset = RESET_ACTIVE then + output.rd_data(7 downto 0) <= (others => '0'); + elsif rising_edge(clock) then + + ua_rd <= '0'; + if input.rd='1' then + -- that's our very simple address decoder + if input.address(0)='0' then + output.rd_data(7 downto 0) <= "0000" & rdrf_iena & tdre_iena & rdrf & tdre; + else + output.rd_data(7 downto 0) <= ua_dout; + ua_rd <= input.rd; + end if; + end if; + + if input.wr='1' then + if input.address(0)='0' then + rdrf_iena <= input.wr_data(3); + tdre_iena <= input.wr_data(2); + end if; + end if; + + end if; + + end process; + + ua_wr <= input.wr and input.address(0); + + intr <= (rdrf and rdrf_iena) or (tdre and tdre_iena); + +-- +-- serial clock +-- + process(clock, reset) + + variable clk16 : integer range 0 to clk16_cnt; + variable clktx : unsigned(3 downto 0); + variable clkrx : unsigned(3 downto 0); + + begin + if reset = RESET_ACTIVE then + clk16 := 0; + clktx := "0000"; + clkrx := "0000"; + tx_clk <= '0'; + rx_clk <= '0'; + rx_buf <= "111"; + + elsif rising_edge(clock) then + + rxd_reg(0) <= rxd; -- to avoid setup timing error in Quartus + rxd_reg(1) <= rxd_reg(0); + rxd_reg(2) <= rxd_reg(1); + + if (clk16=clk16_cnt) then -- 16 x serial clock + clk16 := 0; +-- +-- tx clock +-- + clktx := clktx + 1; + if (clktx="0000") then + tx_clk <= '1'; + else + tx_clk <= '0'; + end if; +-- +-- rx clock +-- + if (rx_clk_ena='1') then + clkrx := clkrx + 1; + if (clkrx="1000") then + rx_clk <= '1'; + else + rx_clk <= '0'; + end if; + else + clkrx := "0000"; + end if; +-- +-- sync in filter buffer +-- + rx_buf(0) <= rxd_reg(2); + rx_buf(2 downto 1) <= rx_buf(1 downto 0); + else + clk16 := clk16 + 1; + tx_clk <= '0'; + rx_clk <= '0'; + end if; + + end if; + + end process; + +-- +-- transmit fifo +-- + cmp_tf: fifo generic map (8, txf_depth, txf_thres) + port map (clock, reset, input.wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half); + + txd <= tsr(0); + tdre <= not tf_full; + +-- +-- state machine for actual shift out +-- + process(clock, reset) + + variable i : integer range 0 to 11; + + begin + + if reset = RESET_ACTIVE then + uart_tx_state <= s0; + tsr <= "1111111111"; + tf_rd <= '0'; + ncts_buf <= "111"; + + elsif rising_edge(clock) then + + ncts_buf(0) <= ncts; + ncts_buf(2 downto 1) <= ncts_buf(1 downto 0); + + case uart_tx_state is + + when s0 => + i := 0; + if (tf_empty='0' and ncts_buf(2)='0') then + uart_tx_state <= s1; + tsr <= tf_dout & '0' & '1'; + tf_rd <= '1'; + end if; + + when s1 => + tf_rd <= '0'; + if (tx_clk='1') then + tsr(9) <= '1'; + tsr(8 downto 0) <= tsr(9 downto 1); + i := i+1; + if (i=11) then -- two stop bits + uart_tx_state <= s0; + end if; + end if; + + end case; + end if; + + end process; + +-- +-- receive fifo +-- + cmp_rf: fifo generic map (8, rxf_depth, rxf_thres) + port map (clock, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half); + + rdrf <= not rf_empty; + nrts <= rf_half; -- glitches even on empty fifo! + +-- +-- filter rxd +-- + with rx_buf select + rx_d <= '0' when "000", + '0' when "001", + '0' when "010", + '1' when "011", + '0' when "100", + '1' when "101", + '1' when "110", + '1' when "111", + 'X' when others; + +-- +-- state machine for actual shift in +-- + process(clock, reset) + + variable i : integer range 0 to 10; + + begin + + if reset = RESET_ACTIVE then + uart_rx_state <= s0; + rsr <= "0000000000"; + rf_wr <= '0'; + rx_clk_ena <= '0'; + + elsif rising_edge(clock) then + + case uart_rx_state is + + when s0 => + i := 0; + rf_wr <= '0'; + if (rx_d='0') then + rx_clk_ena <= '1'; + uart_rx_state <= s1; + else + rx_clk_ena <= '0'; + end if; + + when s1 => + if (rx_clk='1') then + rsr(9) <= rx_d; + rsr(8 downto 0) <= rsr(9 downto 1); + i := i+1; + if (i=10) then + uart_rx_state <= s2; + end if; + end if; + + when s2 => + rx_clk_ena <= '0'; + if rsr(0)='0' and rsr(9)='1' then + if rf_full='0' then -- if full just drop it + rf_wr <= '1'; + end if; + end if; + uart_rx_state <= s0; + + end case; + end if; + + end process; + +end rtl; Index: trunk/vhdl/rom0.mif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/vhdl/rom0.mif =================================================================== --- trunk/vhdl/rom0.mif (nonexistent) +++ trunk/vhdl/rom0.mif (revision 2)
trunk/vhdl/rom0.mif Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/vhdl/ChangeLog =================================================================== --- trunk/vhdl/ChangeLog (nonexistent) +++ trunk/vhdl/ChangeLog (revision 2) @@ -0,0 +1,47 @@ +2007-02-02 Wolfgang Puffitsch + + Version to be published on opencores.org ``Cement and aluminium.'' + +2007-01-31 Wolfgang Puffitsch + + * decode.vhd: restuctured decoder, saving a few LCs + +2007-01-29 Wolfgang Puffitsch + + * alu.vhd: simplified logic to use only one adder/subtractor + + * mem.vhd: removed extra state for SimpCon access + +2007-01-28 Wolfgang Puffitsch + + * mem.vhd: introduced enable-signals for the memories to reduce + power consumption + +2007-01-20 Wolfgang Puffitsch + + * mem.vhd: fixed condition for raising memory interrupt + +2006-12-31 Wolfgang Puffitsch + + * multiplier.vhd: "predicting" unconditional branches now + + * execute.vhd: fixing a bug with calls + + * mem.vhd: fixing a bug with stores to odd addresses + +2006-12-29 Wolfgang Puffitsch + + * intr.vhd: EXC_ERR is triggered by an instruction itself, so it's + wire is left out in the "trigger" signal + + * decode.vhd: now triggering interrupt upon invalid instructions + + * marca_pkg.vhd: introduced constant RESET_ACTIVE for easy + adaption to low-active reset buttons + + * fetch.vhd: reorganized this stage to fix an off-by-one flaw with + the program counter + +2006-12-14 Wolfgang Puffitsch + + First working version ``Starving hysterical naked.'' \ No newline at end of file Index: trunk/vhdl/rom1.mif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/vhdl/rom1.mif =================================================================== --- trunk/vhdl/rom1.mif (nonexistent) +++ trunk/vhdl/rom1.mif (revision 2)
trunk/vhdl/rom1.mif Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/vhdl/regfile.vhd =================================================================== --- trunk/vhdl/regfile.vhd (nonexistent) +++ trunk/vhdl/regfile.vhd (revision 2) @@ -0,0 +1,77 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA decode stage +------------------------------------------------------------------------------- +-- architecture for the instruction-decode pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; + +architecture behaviour of regfile is + +type registers is array (REG_COUNT-1 downto 0) of std_logic_vector(REG_WIDTH-1 downto 0); + +signal regs, next_regs : registers; + +begin -- behaviour + + syn_proc: process (clock, reset) + begin -- process syn_proc + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + regs <= (others => (others => '0')); + elsif clock'event and clock = '1' then -- rising clock edge + if hold = '0' then + regs <= next_regs; + end if; + end if; + end process syn_proc; + + forward: process(rd1_addr, rd2_addr, wr_ena, wr_addr, wr_val, regs) + begin -- process forward + + next_regs <= regs; + + if wr_ena = '1' then + next_regs(to_integer(unsigned(wr_addr))) <= wr_val; + end if; + + if rd1_addr /= wr_addr or wr_ena = '0' then + rd1_val <= regs(to_integer(unsigned(rd1_addr))); + else + rd1_val <= wr_val; + end if; + + if rd2_addr /= wr_addr or wr_ena = '0' then + rd2_val <= regs(to_integer(unsigned(rd2_addr))); + else + rd2_val <= wr_val; + end if; + + end process forward; + +end behaviour; Index: trunk/vhdl/alu.vhd =================================================================== --- trunk/vhdl/alu.vhd (nonexistent) +++ trunk/vhdl/alu.vhd (revision 2) @@ -0,0 +1,613 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA ALU +------------------------------------------------------------------------------- +-- architecture for the ALU +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; + +architecture behaviour of alu is + + type WAIT_STATE is (WAIT_NONE, WAIT_MULT, WAIT_DIV, WAIT_UDIV, WAIT_MOD, WAIT_UMOD); + signal state : WAIT_STATE; + signal next_state : WAIT_STATE; + + signal flags : std_logic_vector(REG_WIDTH-1 downto 0); + signal next_flags : std_logic_vector(REG_WIDTH-1 downto 0); + + signal shflags : std_logic_vector(REG_WIDTH-1 downto 0); + signal next_shflags : std_logic_vector(REG_WIDTH-1 downto 0); + + signal old_sgna, old_sgnb : std_logic; + signal sgna, sgnb : std_logic; + + component multiplier is + generic ( + width : integer := REG_WIDTH); + port ( + clock : in std_logic; + reset : in std_logic; + trigger : in std_logic; + operand1 : in std_logic_vector(width-1 downto 0); + operand2 : in std_logic_vector(width-1 downto 0); + busy : out std_logic; + product : out std_logic_vector(width downto 0)); + end component; + + signal mult_op1 : std_logic_vector(REG_WIDTH-1 downto 0); + signal mult_op2 : std_logic_vector(REG_WIDTH-1 downto 0); + signal mult_trigger : std_logic; + signal mult_busy : std_logic; + signal mult_result : std_logic_vector(REG_WIDTH downto 0); + + + component divider is + generic ( + width : integer := REG_WIDTH); + port ( + clock : in std_logic; + reset : in std_logic; + trigger : in std_logic; + denom : in std_logic_vector(width-1 downto 0); + numer : in std_logic_vector(width-1 downto 0); + exc : out std_logic; + busy : out std_logic; + quotient : out std_logic_vector(width-1 downto 0); + remain : out std_logic_vector(width-1 downto 0)); + end component; + + signal udiv_op1 : std_logic_vector(REG_WIDTH-1 downto 0); + signal udiv_op2 : std_logic_vector(REG_WIDTH-1 downto 0); + signal udiv_trigger : std_logic; + signal udiv_exc : std_logic; + signal udiv_busy : std_logic; + signal udiv_result : std_logic_vector(REG_WIDTH-1 downto 0); + signal umod_result : std_logic_vector(REG_WIDTH-1 downto 0); + + + signal adder_op1 : std_logic_vector(REG_WIDTH downto 0); + signal adder_op2 : std_logic_vector(REG_WIDTH downto 0); + signal adder_op3 : std_logic; + signal adder_result : std_logic_vector(REG_WIDTH downto 0); + + + function shift_left (a : std_logic_vector; + b : std_logic_vector) + return std_logic_vector is + variable result : std_logic_vector(a'length-1 downto 0); + variable i : integer; + begin + for i in 0 to a'length-1 loop + if i < to_integer(unsigned(b)) then + result(i) := '0'; + else + result(i) := a(i - to_integer(unsigned(b))); + end if; + end loop; + return result; + end; + + function shift_right (a : std_logic_vector; + b : std_logic_vector) + return std_logic_vector is + variable result : std_logic_vector(a'length-1 downto 0); + variable i : integer; + begin + for i in 0 to a'length-1 loop + if i < to_integer(unsigned(b)) then + result(i) := a(i + to_integer(unsigned(b))); + elsif i < a'length-1 then + result(i) := '0'; + else + result(i) := a(to_integer(unsigned(b)) - 1); + end if; + end loop; + return result; + end; + + function shift_aright (a : std_logic_vector; + b : std_logic_vector) + return std_logic_vector is + variable result : std_logic_vector(a'length-1 downto 0); + variable i : integer; + begin + for i in 0 to a'length-1 loop + if i < to_integer(unsigned(b)) then + result(i) := a(i + to_integer(unsigned(b))); + elsif i < a'length-1 then + result(i) := a(a'length-1); + else + result(i) := a(to_integer(unsigned(b)) - 1); + end if; + end loop; + return result; + end; + + function rotate_left (a : std_logic_vector; + b : std_logic_vector; + c : std_logic) + return std_logic_vector is + variable result : std_logic_vector(a'length-1 downto 0); + variable i : integer; + begin + for i in 0 to a'length-1 loop + if i < to_integer(unsigned(b)) - 1 then + result(i) := a(a'length - to_integer(unsigned(b)) + i); + elsif i = to_integer(unsigned(b)) - 1 then + result(i) := c; + else + result(i) := a(i - to_integer(unsigned(b))); + end if; + end loop; + return result; + end; + + function rotate_right(a : std_logic_vector; + b : std_logic_vector; + c : std_logic) + return std_logic_vector is + variable result : std_logic_vector(a'length-1 downto 0); + variable i : integer; + begin + for i in 0 to a'length-1 loop + if i < a'length - to_integer(unsigned(b)) then + result(i) := a(to_integer(unsigned(b)) + i); + elsif i = a'length - to_integer(unsigned(b)) - 1 then + result(i) := c; + else + result(i) := a(i - a'length - to_integer(unsigned(b))); + end if; + end loop; + return result; + end; + + function to_unsigned(a : std_logic) + return unsigned is + variable result : unsigned(0 downto 0); + begin -- to_unsigned + if a = '1' then + result := "1"; + else + result := "0"; + end if; + return result; + end to_unsigned; + + function parity(a : std_logic_vector) + return std_logic is + variable result : std_logic; + variable i : integer; + begin + result := '1'; + for i in a'low to a'high loop + result := result xor a(i); + end loop; + return result; + end; + +begin -- behaviour + + -- hardwire the interrupt enable flag + iena <= flags(FLAG_I); + -- and the exception signal to the divider + exc <= udiv_exc; + + mult_unit : multiplier + port map ( + clock => clock, + reset => reset, + trigger => mult_trigger, + operand1 => mult_op1, + operand2 => mult_op2, + busy => mult_busy, + product => mult_result); + + udiv_unit : divider + port map ( + clock => clock, + reset => reset, + trigger => udiv_trigger, + numer => udiv_op1, + denom => udiv_op2, + exc => udiv_exc, + busy => udiv_busy, + quotient => udiv_result, + remain => umod_result); + + syn_proc: process (clock, reset) + begin -- process syn_proc + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + flags <= (others => '0'); + shflags <= (others => '0'); + state <= WAIT_NONE; + old_sgna <= '0'; + old_sgnb <= '0'; + elsif clock'event and clock = '1' then -- rising clock edge + flags <= next_flags; + shflags <= next_shflags; + state <= next_state; + old_sgna <= sgna; + old_sgnb <= sgnb; + end if; + end process syn_proc; + + business: process(next_state) + begin -- process business + if next_state /= WAIT_NONE then + busy <= '1'; + else + busy <= '0'; + end if; + end process business; + + adder: process (adder_op1, adder_op2, adder_op3) + begin -- process adder + adder_result <= std_logic_vector(unsigned(adder_op1) + unsigned(adder_op2) + + to_unsigned(adder_op3)); + end process adder; + + compute: process (state, op, a, b, i, pc, flags, shflags, + intr, + sgna, sgnb, old_sgna, old_sgnb, + mult_busy, mult_result, + udiv_busy, udiv_result, umod_result, + adder_result) + + variable wr_flags : std_logic; + variable tmp : std_logic_vector(REG_WIDTH downto 0); + + begin + wr_flags := '1'; + tmp := (others => '0'); + + next_flags <= flags; + next_shflags <= shflags; + next_state <= state; + + sgna <= a(REG_WIDTH-1); + sgnb <= b(REG_WIDTH-1); + + mult_op1 <= (others => '0'); + mult_op2 <= (others => '0'); + mult_trigger <= '0'; + + udiv_op1 <= (others => '0'); + udiv_op2 <= (others => '0'); + udiv_trigger <= '0'; + + adder_op1 <= (others => '0'); + adder_op2 <= (others => '0'); + adder_op3 <= '0'; + + pcchg <= '0'; + + case state is + when WAIT_MULT => + sgna <= old_sgna; + sgnb <= old_sgnb; + tmp := mult_result; + if mult_busy = '0' then + next_state <= WAIT_NONE; + end if; + when WAIT_DIV => + sgna <= old_sgna; + sgnb <= old_sgnb; + if sgna = sgnb then + tmp(REG_WIDTH-1 downto 0) := udiv_result; + else + tmp(REG_WIDTH-1 downto 0) := std_logic_vector(-signed(udiv_result)); + end if; + if udiv_busy = '0' then + next_state <= WAIT_NONE; + end if; + when WAIT_UDIV => + sgna <= old_sgna; + sgnb <= old_sgnb; + tmp(REG_WIDTH-1 downto 0) := udiv_result; + if udiv_busy = '0' then + next_state <= WAIT_NONE; + end if; + when WAIT_MOD => + sgna <= old_sgna; + sgnb <= old_sgnb; + if sgna = sgnb then + tmp(REG_WIDTH-1 downto 0) := umod_result; + else + tmp(REG_WIDTH-1 downto 0) := std_logic_vector(-signed(umod_result)); + end if; + if udiv_busy = '0' then + next_state <= WAIT_NONE; + end if; + when WAIT_UMOD => + sgna <= old_sgna; + sgnb <= old_sgnb; + tmp(REG_WIDTH-1 downto 0) := umod_result; + if udiv_busy = '0' then + next_state <= WAIT_NONE; + end if; + when WAIT_NONE => + case op is + when ALU_ADD => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1)); + adder_op2 <= std_logic_vector(resize(unsigned(b), REG_WIDTH+1)); + tmp := adder_result; + when ALU_SUB => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1)); + adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1)); + adder_op3 <= '1'; + tmp := adder_result; + when ALU_ADDC => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1)); + adder_op2 <= std_logic_vector(resize(unsigned(b), REG_WIDTH+1)); + adder_op3 <= flags(FLAG_C); + tmp := adder_result; + when ALU_SUBC => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1)); + adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1)); + adder_op3 <= not flags(FLAG_C); + tmp := adder_result; + when ALU_AND => tmp(REG_WIDTH-1 downto 0) := a and b; + when ALU_OR => tmp(REG_WIDTH-1 downto 0) := a or b; + when ALU_XOR => tmp(REG_WIDTH-1 downto 0) := a xor b; +------------------------------------------------------------------------------- + when ALU_MUL => mult_trigger <= '1'; + mult_op1 <= a; + mult_op2 <= b; + next_state <= WAIT_MULT; + when ALU_DIV => udiv_trigger <= '1'; + udiv_op1 <= std_logic_vector(abs(signed(a))); + udiv_op2 <= std_logic_vector(abs(signed(b))); + next_state <= WAIT_DIV; + when ALU_UDIV => udiv_trigger <= '1'; + udiv_op1 <= a; + udiv_op2 <= b; + next_state <= WAIT_UDIV; + when ALU_MOD => udiv_trigger <= '1'; + udiv_op1 <= std_logic_vector(abs(signed(a))); + udiv_op2 <= std_logic_vector(abs(signed(b))); + next_state <= WAIT_MOD; + when ALU_UMOD => udiv_trigger <= '1'; + udiv_op1 <= a; + udiv_op2 <= b; + next_state <= WAIT_UMOD; +------------------------------------------------------------------------------- + when ALU_LDIL => tmp(REG_WIDTH-1 downto 0) := a(REG_WIDTH-1 downto REG_WIDTH/2) & i(REG_WIDTH/2-1 downto 0); + when ALU_LDIH => tmp(REG_WIDTH-1 downto 0) := i(REG_WIDTH/2-1 downto 0) & a(REG_WIDTH/2-1 downto 0); + when ALU_LDIB => tmp(REG_WIDTH-1 downto 0) := i; +------------------------------------------------------------------------------- + when ALU_MOV => tmp(REG_WIDTH-1 downto 0) := b; + when ALU_NOT => tmp(REG_WIDTH-1 downto 0) := not b; + when ALU_NEG => adder_op1 <= (others => '0'); + adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1)); + adder_op3 <= '1'; + tmp := adder_result; + when ALU_ADDI => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1)); + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + tmp := adder_result; + sgnb <= i(REG_WIDTH-1); + when ALU_CMPI => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1)); + adder_op2 <= not std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + adder_op3 <= '1'; + tmp := adder_result; + sgnb <= i(REG_WIDTH-1); + when ALU_SHL => tmp := shift_left (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b); + when ALU_SHR => tmp := shift_right (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b); + when ALU_SAR => tmp := shift_aright (std_logic_vector(resize( signed(a), REG_WIDTH+1)), b); + when ALU_ROLC => tmp := rotate_left (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b(REG_WIDTH_LOG-1 downto 0), flags(FLAG_C)); + when ALU_RORC => tmp := rotate_right (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b(REG_WIDTH_LOG-1 downto 0), flags(FLAG_C)); + when ALU_BSET => tmp(REG_WIDTH-1 downto 0) := a; tmp(to_integer(unsigned(i))) := '1'; + when ALU_BCLR => tmp(REG_WIDTH-1 downto 0) := a; tmp(to_integer(unsigned(i))) := '0'; + when ALU_BTEST => tmp := (others => '0'); tmp(0) := a(to_integer(unsigned(i))); + when ALU_SEXT => tmp(REG_WIDTH-1 downto 0) := std_logic_vector(resize(signed(a(REG_WIDTH/2-1 downto 0)), REG_WIDTH)); +------------------------------------------------------------------------------- + when ALU_BRZ => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '1' then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRNZ => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '0' then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRLE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '1' or flags(FLAG_N) /= flags(FLAG_V) then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRLT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '0' and flags(FLAG_N) /= flags(FLAG_V) then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRGE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '1' or flags(FLAG_N) = flags(FLAG_V) then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRGT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '0' and flags(FLAG_N) = flags(FLAG_V) then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRULE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '1' or flags(FLAG_C) = '1' then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRULT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '0' and flags(FLAG_C) = '1' then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRUGE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '1' or flags(FLAG_C) = '0' then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; + when ALU_BRUGT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1)); + if flags(FLAG_Z) = '0' and flags(FLAG_C) = '0' then + adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1)); + pcchg <= '1'; + end if; + tmp := adder_result; + wr_flags := '0'; +------------------------------------------------------------------------------- + when ALU_JMP => tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + wr_flags := '0'; + when ALU_JMPZ => if flags(FLAG_Z) = '1' then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPNZ => if flags(FLAG_Z) = '0' then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPLE => if flags(FLAG_Z) = '1' or flags(FLAG_N) /= flags(FLAG_V) then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPLT => if flags(FLAG_Z) = '0' and flags(FLAG_N) /= flags(FLAG_V) then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPGE => if flags(FLAG_Z) = '1' or flags(FLAG_N) = flags(FLAG_V) then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPGT => if flags(FLAG_Z) = '0' and flags(FLAG_N) = flags(FLAG_V) then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPULE => if flags(FLAG_Z) = '1' or flags(FLAG_C) = '1' then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPULT => if flags(FLAG_Z) = '0' and flags(FLAG_C) = '1' then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPUGE => if flags(FLAG_Z) = '1' or flags(FLAG_C) = '0' then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; + when ALU_JMPUGT => if flags(FLAG_Z) = '0' and flags(FLAG_C) = '0' then + tmp(REG_WIDTH-1 downto 0) := a; + pcchg <= '1'; + else + tmp(REG_WIDTH-1 downto 0) := pc; + end if; + wr_flags := '0'; +------------------------------------------------------------------------------- + when ALU_GETFL => tmp(REG_WIDTH-1 downto 0) := flags; + wr_flags := '0'; + when ALU_SETFL => next_flags <= a; + wr_flags := '0'; + when ALU_GETSHFL => tmp(REG_WIDTH-1 downto 0) := shflags; + wr_flags := '0'; + when ALU_SETSHFL => next_shflags <= a; + wr_flags := '0'; + when ALU_INTR => next_shflags <= flags; + next_flags(FLAG_I) <= '0'; + wr_flags := '0'; + when ALU_RETI => next_flags <= shflags; + wr_flags := '0'; + when ALU_SEI => next_flags(FLAG_I) <= '1'; + wr_flags := '0'; + when ALU_CLI => next_flags(FLAG_I) <= '0'; + wr_flags := '0'; +------------------------------------------------------------------------------- + when ALU_NOP => wr_flags := '0'; + when others => null; + end case; + when others => null; + end case; + + -- if the result is to be ignored, it will be ignored in the write-back stage + result <= tmp(REG_WIDTH-1 downto 0); + + -- the flags do not make sense with all instructions yet + if wr_flags = '1' then + next_flags(FLAG_C) <= tmp(REG_WIDTH); + next_flags(FLAG_N) <= tmp(REG_WIDTH-1); + next_flags(FLAG_Z) <= zero(tmp(REG_WIDTH-1 downto 0)); + next_flags(FLAG_V) <= sgna xor sgnb xor tmp(REG_WIDTH) xor tmp(REG_WIDTH-1); + next_flags(FLAG_P) <= parity(tmp(REG_WIDTH-1 downto 0)); + end if; + + if intr = '1' then + next_shflags <= flags; + next_flags(FLAG_I) <= '0'; + end if; + + end process compute; + +end behaviour; Index: trunk/vhdl/decode.vhd =================================================================== --- trunk/vhdl/decode.vhd (nonexistent) +++ trunk/vhdl/decode.vhd (revision 2) @@ -0,0 +1,690 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA decode stage +------------------------------------------------------------------------------- +-- architecture for the instruction-decode pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; + +architecture behaviour of decode is + +signal pc_reg : std_logic_vector(REG_WIDTH-1 downto 0); +signal dest_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal instr_reg : std_logic_vector(PDATA_WIDTH-1 downto 0); + +signal src1_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal src2_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0); + +component regfile is + port ( + clock : in std_logic; + reset : in std_logic; + hold : in std_logic; + rd1_addr : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + rd2_addr : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + rd1_val : out std_logic_vector(REG_WIDTH-1 downto 0); + rd2_val : out std_logic_vector(REG_WIDTH-1 downto 0); + wr_ena : in std_logic; + wr_addr : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + wr_val : in std_logic_vector(REG_WIDTH-1 downto 0)); +end component; + +begin -- behaviour + + regfile_unit : regfile + port map ( + clock => clock, + reset => reset, + hold => hold, + rd1_addr => src1_reg, + rd2_addr => src2_reg, + rd1_val => op1, + rd2_val => op2, + wr_ena => wr_ena, + wr_addr => wr_dest, + wr_val => wr_val); + + syn_proc: process (clock, reset) + begin -- process syn_proc + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + pc_reg <= (others => '0'); + dest_reg <= (others => '0'); + instr_reg <= OPC_PFX_C & OPC_PFX_C2 & OPC_PFX_C2a & OPC_NOP; + src1_reg <= (others => '0'); + src2_reg <= (others => '0'); + elsif clock'event and clock = '1' then -- rising clock edge + if hold = '0' then + if stall = '1' then + pc_reg <= (others => '0'); + dest_reg <= (others => '0'); + instr_reg <= OPC_PFX_C & OPC_PFX_C2 & OPC_PFX_C2a & OPC_NOP; + src1_reg <= (others => '0'); + src2_reg <= (others => '0'); + else + pc_reg <= pc_in; + dest_reg <= dest_in; + instr_reg <= instr; + src1_reg <= src1_in; + src2_reg <= src2_in; + end if; + end if; + end if; + end process syn_proc; + + feedthrough: process (pc_reg, src1_reg, src2_reg) + begin -- process feedthrough + pc_out <= pc_reg; + src1_out <= src1_reg; + src2_out <= src2_reg; + end process feedthrough; + + do_decode: process (instr_reg, src1_reg, src2_reg, dest_reg) + begin -- process + + -- all unknown opcodes trigger interrupt EXC_ERR + imm <= std_logic_vector(to_unsigned(EXC_ERR, REG_WIDTH)); + dest_out <= dest_reg; + aop <= ALU_INTR; + mop <= MEM_NOP; + iop <= INTR_INTR; + unit <= UNIT_INTR; + target <= TARGET_PC; + + case instr_reg(PDATA_WIDTH-1 downto PDATA_WIDTH-4) is + when + OPC_ADD => aop <= ALU_ADD; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_SUB => aop <= ALU_SUB; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_ADDC => aop <= ALU_ADDC; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_SUBC => aop <= ALU_SUBC; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_AND => aop <= ALU_AND; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_OR => aop <= ALU_OR; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_XOR => aop <= ALU_XOR; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_MUL => aop <= ALU_MUL; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_DIV => aop <= ALU_DIV; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_UDIV => aop <= ALU_UDIV; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= dest_reg; + when + OPC_LDIL => imm <= std_logic_vector(resize(signed(dest_reg & src2_reg), REG_WIDTH)); + aop <= ALU_LDIL; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_LDIH => imm <= std_logic_vector(resize(signed(dest_reg & src2_reg), REG_WIDTH)); + aop <= ALU_LDIH; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_LDIB => imm <= std_logic_vector(resize(signed(dest_reg & src2_reg), REG_WIDTH)); + aop <= ALU_LDIB; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + + when + OPC_PFX_A => + case instr_reg(PDATA_WIDTH-5 downto PDATA_WIDTH-8) is + when + OPC_MOV => aop <= ALU_MOV; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_MOD => aop <= ALU_MOD; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_UMOD => aop <= ALU_UMOD; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_NOT => aop <= ALU_NOT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_NEG => aop <= ALU_NEG; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_CMP => aop <= ALU_SUB; -- it's the same + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_ADDI => imm <= std_logic_vector(resize(signed(src2_reg), REG_WIDTH)); + aop <= ALU_ADDI; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_CMPI => imm <= std_logic_vector(resize(signed(src2_reg), REG_WIDTH)); + aop <= ALU_CMPI; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_SHL => aop <= ALU_SHL; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_SHR => aop <= ALU_SHR; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_SAR => aop <= ALU_SAR; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_ROLC => aop <= ALU_ROLC; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_RORC => aop <= ALU_RORC; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_BSET => imm <= std_logic_vector(resize(unsigned(src2_reg), REG_WIDTH)); + aop <= ALU_BSET; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_BCLR => imm <= std_logic_vector(resize(unsigned(src2_reg), REG_WIDTH)); + aop <= ALU_BCLR; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_BTEST => imm <= std_logic_vector(resize(unsigned(src2_reg), REG_WIDTH)); + aop <= ALU_BTEST; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when others => null; + end case; + + when OPC_PFX_B => + case instr_reg(PDATA_WIDTH-5 downto PDATA_WIDTH-8) is + when + OPC_LOAD => mop <= MEM_LOAD; + aop <= ALU_NOP; + iop <= INTR_NOP; + unit <= UNIT_MEM; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_LOADL => mop <= MEM_LOADL; + aop <= ALU_NOP; + iop <= INTR_NOP; + unit <= UNIT_MEM; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_LOADH => mop <= MEM_LOADH; + aop <= ALU_NOP; + iop <= INTR_NOP; + unit <= UNIT_MEM; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_LOADB => mop <= MEM_LOADB; + aop <= ALU_NOP; + iop <= INTR_NOP; + unit <= UNIT_MEM; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_STORE => mop <= MEM_STORE; + aop <= ALU_NOP; + iop <= INTR_NOP; + unit <= UNIT_MEM; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_STOREL => mop <= MEM_STOREL; + aop <= ALU_NOP; + iop <= INTR_NOP; + unit <= UNIT_MEM; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_STOREH => mop <= MEM_STOREH; + aop <= ALU_NOP; + iop <= INTR_NOP; + unit <= UNIT_MEM; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_CALL => aop <= ALU_JMP; -- force alu_pcchg + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_CALL; + target <= TARGET_BOTH; + dest_out <= src1_reg; + when others => null; + end case; + + when OPC_PFX_C => + case instr_reg(PDATA_WIDTH-5 downto PDATA_WIDTH-8) is + when + OPC_BR => aop <= ALU_NOP; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_BRZ => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRZ; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRNZ => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRNZ; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRLE => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRLE; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRLT => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRLT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRGE => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRGE; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRGT => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRGT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRULE => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRULE; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRULT => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRULT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRUGE => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRUGE; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_BRUGT => imm <= std_logic_vector(resize(signed(src2_reg & src1_reg), REG_WIDTH)); + aop <= ALU_BRUGT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_SEXT => aop <= ALU_SEXT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_LDVEC => imm <= std_logic_vector(resize(unsigned(src2_reg), REG_WIDTH)); + iop <= INTR_LDVEC; + aop <= ALU_NOP; + mop <= MEM_NOP; + unit <= UNIT_INTR; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_STVEC => imm <= std_logic_vector(resize(unsigned(src2_reg), REG_WIDTH)); + iop <= INTR_STVEC; + aop <= ALU_NOP; + mop <= MEM_NOP; + unit <= UNIT_INTR; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_PFX_C1 => + case instr_reg(PDATA_WIDTH-9 downto PDATA_WIDTH-12) is + when + OPC_JMP => aop <= ALU_JMP; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPZ => aop <= ALU_JMPZ; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPNZ => aop <= ALU_JMPNZ; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPLE => aop <= ALU_JMPLE; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPLT => aop <= ALU_JMPLT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPGE => aop <= ALU_JMPGE; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPGT => aop <= ALU_JMPGT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPULE => aop <= ALU_JMPULE; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPULT => aop <= ALU_JMPULT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPUGE => aop <= ALU_JMPUGE; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_JMPUGT => aop <= ALU_JMPUGT; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_INTR => imm <= std_logic_vector(resize(unsigned(src1_reg), REG_WIDTH)); + aop <= ALU_INTR; + iop <= INTR_INTR; + mop <= MEM_NOP; + unit <= UNIT_INTR; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_GETFL => aop <= ALU_GETFL; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_SETFL => aop <= ALU_SETFL; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_GETIRA => iop <= INTR_GETIRA; + aop <= ALU_NOP; + mop <= MEM_NOP; + unit <= UNIT_INTR; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + + when + OPC_SETIRA => iop <= INTR_SETIRA; + aop <= ALU_NOP; + mop <= MEM_NOP; + unit <= UNIT_INTR; + target <= TARGET_NONE; + dest_out <= src1_reg; + when others => null; + end case; + + when + OPC_PFX_C2 => + case instr_reg(PDATA_WIDTH-9 downto PDATA_WIDTH-12) is + when + OPC_GETSHFL => aop <= ALU_GETSHFL; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_REGISTER; + dest_out <= src1_reg; + when + OPC_SETSHFL => aop <= ALU_SETSHFL; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_PFX_C2a => + case instr_reg(PDATA_WIDTH-13 downto PDATA_WIDTH-16) is + when + OPC_RETI => aop <= ALU_RETI; + iop <= INTR_RETI; + mop <= MEM_NOP; + unit <= UNIT_INTR; + target <= TARGET_PC; + dest_out <= src1_reg; + when + OPC_NOP => aop <= ALU_NOP; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_SEI => aop <= ALU_SEI; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when + OPC_CLI => aop <= ALU_CLI; + mop <= MEM_NOP; + iop <= INTR_NOP; + unit <= UNIT_ALU; + target <= TARGET_NONE; + dest_out <= src1_reg; + when others => null; + end case; + when others => null; + end case; + when others => null; + end case; + when others => null; + end case; + + end process; + +end behaviour; Index: trunk/vhdl/marca.vhd =================================================================== --- trunk/vhdl/marca.vhd (nonexistent) +++ trunk/vhdl/marca.vhd (revision 2) @@ -0,0 +1,288 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA top level architecture +------------------------------------------------------------------------------- +-- architecture of the processor itself +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +architecture behaviour of marca is + +component fetch + port ( + clock : in std_logic; + reset : in std_logic; + + hold : in std_logic; + + pcena : in std_logic; + pc_in : in std_logic_vector(REG_WIDTH-1 downto 0); + pc_out : out std_logic_vector(REG_WIDTH-1 downto 0); + + src1 : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + src2 : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + dest : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + instr : out std_logic_vector(PDATA_WIDTH-1 downto 0)); +end component; + +signal fetch_pc : std_logic_vector(REG_WIDTH-1 downto 0); +signal fetch_src1 : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal fetch_src2 : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal fetch_dest : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal fetch_instr : std_logic_vector(PDATA_WIDTH-1 downto 0); + +component decode + port ( + clock : in std_logic; + reset : in std_logic; + + hold : in std_logic; + stall : in std_logic; + + pc_in : in std_logic_vector(REG_WIDTH-1 downto 0); + pc_out : out std_logic_vector(REG_WIDTH-1 downto 0); + + instr : in std_logic_vector(PDATA_WIDTH-1 downto 0); + + src1_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + src1_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + src2_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + src2_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + + dest_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + dest_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + + aop : out ALU_OP; + mop : out MEM_OP; + iop : out INTR_OP; + + op1 : out std_logic_vector(REG_WIDTH-1 downto 0); + op2 : out std_logic_vector(REG_WIDTH-1 downto 0); + imm : out std_logic_vector(REG_WIDTH-1 downto 0); + + unit : out UNIT_SELECTOR; + target : out TARGET_SELECTOR; + + wr_ena : in std_logic; + wr_dest : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + wr_val : in std_logic_vector(REG_WIDTH-1 downto 0)); +end component; + +signal decode_pc : std_logic_vector(REG_WIDTH-1 downto 0); +signal decode_op1 : std_logic_vector(REG_WIDTH-1 downto 0); +signal decode_op2 : std_logic_vector(REG_WIDTH-1 downto 0); +signal decode_imm : std_logic_vector(REG_WIDTH-1 downto 0); +signal decode_src1 : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal decode_src2 : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal decode_dest : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal decode_aop : ALU_OP; +signal decode_mop : MEM_OP; +signal decode_iop : INTR_OP; +signal decode_unit : UNIT_SELECTOR; +signal decode_target : TARGET_SELECTOR; +signal decode_instr : std_logic_vector(PDATA_WIDTH-1 downto 0); + +component execute is + port ( + clock : in std_logic; + reset : in std_logic; + + busy : out std_logic; + stall : in std_logic; + + pc_in : in std_logic_vector(REG_WIDTH-1 downto 0); + pcchg : out std_logic; + pc_out : out std_logic_vector(REG_WIDTH-1 downto 0); + + dest_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + dest_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + + src1 : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + src2 : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + + aop : in ALU_OP; + mop : in MEM_OP; + iop : in INTR_OP; + + op1 : in std_logic_vector(REG_WIDTH-1 downto 0); + op2 : in std_logic_vector(REG_WIDTH-1 downto 0); + imm : in std_logic_vector(REG_WIDTH-1 downto 0); + + unit : in UNIT_SELECTOR; + target_in : in TARGET_SELECTOR; + target_out : out TARGET_SELECTOR; + + result : out std_logic_vector(REG_WIDTH-1 downto 0); + + fw_ena : in std_logic; + fw_dest : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + fw_val : in std_logic_vector(REG_WIDTH-1 downto 0); + + ext_in : in std_logic_vector(IN_BITS-1 downto 0); + ext_out : out std_logic_vector(OUT_BITS-1 downto 0)); +end component; + +signal exec_busy : std_logic; +signal exec_pcchg : std_logic; +signal exec_pc : std_logic_vector(REG_WIDTH-1 downto 0); +signal exec_dest : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal exec_target : TARGET_SELECTOR; +signal exec_result : std_logic_vector(REG_WIDTH-1 downto 0); + +component writeback is + port ( + clock : in std_logic; + reset : in std_logic; + + hold : in std_logic; + + pc_in : in std_logic_vector(REG_WIDTH-1 downto 0); + pcchg : in std_logic; + pc_out : out std_logic_vector(REG_WIDTH-1 downto 0); + pcena : out std_logic; + + dest_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + dest_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + + target : in TARGET_SELECTOR; + result : in std_logic_vector(REG_WIDTH-1 downto 0); + + ena : out std_logic; + val : out std_logic_vector(REG_WIDTH-1 downto 0)); +end component; + +signal wb_pc : std_logic_vector(REG_WIDTH-1 downto 0); +signal wb_pcena : std_logic; +signal wb_dest : std_logic_vector(REG_COUNT_LOG-1 downto 0); +signal wb_ena : std_logic; +signal wb_val : std_logic_vector(REG_WIDTH-1 downto 0); + +signal decode_stall : std_logic; + +signal reset : std_logic; +signal meta_reset : std_logic; + +begin -- behaviour + + -- in the decode and execution stage we need to stall a little earlier + decode_stall <= exec_pcchg or wb_pcena; + + fetch_stage : fetch + port map ( + clock => clock, + reset => reset, + hold => exec_busy, + pcena => wb_pcena, + pc_in => wb_pc, + pc_out => fetch_pc, + src1 => fetch_src1, + src2 => fetch_src2, + dest => fetch_dest, + instr => fetch_instr); + + decode_stage : decode + port map ( + clock => clock, + reset => reset, + hold => exec_busy, + stall => decode_stall, + pc_in => fetch_pc, + pc_out => decode_pc, + instr => fetch_instr, + src1_in => fetch_src1, + src1_out => decode_src1, + src2_in => fetch_src2, + src2_out => decode_src2, + dest_in => fetch_dest, + dest_out => decode_dest, + aop => decode_aop, + mop => decode_mop, + iop => decode_iop, + op1 => decode_op1, + op2 => decode_op2, + imm => decode_imm, + unit => decode_unit, + target => decode_target, + wr_ena => wb_ena, + wr_dest => wb_dest, + wr_val => wb_val); + + execution_stage : execute + port map ( + clock => clock, + reset => reset, + busy => exec_busy, + stall => exec_pcchg, + pc_in => decode_pc, + pcchg => exec_pcchg, + pc_out => exec_pc, + dest_in => decode_dest, + dest_out => exec_dest, + src1 => decode_src1, + src2 => decode_src2, + aop => decode_aop, + mop => decode_mop, + iop => decode_iop, + op1 => decode_op1, + op2 => decode_op2, + imm => decode_imm, + unit => decode_unit, + target_in => decode_target, + target_out => exec_target, + result => exec_result, + fw_ena => wb_ena, + fw_dest => wb_dest, + fw_val => wb_val, + ext_in => ext_in, + ext_out => ext_out); + + writeback_stage : writeback + port map ( + clock => clock, + reset => reset, + hold => exec_busy, + pc_in => exec_pc, + pcchg => exec_pcchg, + pc_out => wb_pc, + pcena => wb_pcena, + dest_in => exec_dest, + dest_out => wb_dest, + target => exec_target, + result => exec_result, + ena => wb_ena, + val => wb_val); + + synchronize: process (clock, ext_reset, meta_reset) + begin + if clock'event and clock = '1' then + meta_reset <= ext_reset; + reset <= meta_reset; + end if; + end process synchronize; + +end behaviour; Index: trunk/vhdl/regfile_ent.vhd =================================================================== --- trunk/vhdl/regfile_ent.vhd (nonexistent) +++ trunk/vhdl/regfile_ent.vhd (revision 2) @@ -0,0 +1,48 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA decode stage +------------------------------------------------------------------------------- +-- entity of the instruction-decode pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity regfile is + + port ( + clock : in std_logic; + reset : in std_logic; + hold : in std_logic; + rd1_addr : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + rd2_addr : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + rd1_val : out std_logic_vector(REG_WIDTH-1 downto 0); + rd2_val : out std_logic_vector(REG_WIDTH-1 downto 0); + wr_ena : in std_logic; + wr_addr : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + wr_val : in std_logic_vector(REG_WIDTH-1 downto 0)); + +end regfile; Index: trunk/vhdl/data_rom.vhd =================================================================== --- trunk/vhdl/data_rom.vhd (nonexistent) +++ trunk/vhdl/data_rom.vhd (revision 2) @@ -0,0 +1,166 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: data_rom.vhd +-- Megafunction Name(s): +-- altsyncram +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 6.0 Build 202 06/20/2006 SP 1 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2006 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY data_rom IS + GENERIC + ( + init_file : STRING + ); + PORT + ( + address : IN STD_LOGIC_VECTOR (6 DOWNTO 0); + clken : IN STD_LOGIC ; + clock : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END data_rom; + + +ARCHITECTURE SYN OF data_rom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_aclr_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + clocken0 : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (6 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + init_file => init_file, + intended_device_family => "Cyclone", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 128, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "UNREGISTERED", + widthad_a => 7, + width_a => 8, + width_byteena_a => 1 + ) + PORT MAP ( + clocken0 => clken, + clock0 => clock, + address_a => address, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "1" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "src/rom.mif" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "128" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "7" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: INIT_FILE STRING "src/rom.mif" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "128" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "7" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 7 0 INPUT NODEFVAL address[6..0] +-- Retrieval info: USED_PORT: clken 0 0 0 0 INPUT NODEFVAL clken +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0] +-- Retrieval info: CONNECT: @address_a 0 0 7 0 address 0 0 7 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: @clocken0 0 0 0 0 clken 0 0 0 0 +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_rom.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_rom.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_rom.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_rom.bsf TRUE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL data_rom_inst.vhd FALSE Index: trunk/vhdl/divider.vhd =================================================================== --- trunk/vhdl/divider.vhd (nonexistent) +++ trunk/vhdl/divider.vhd (revision 2) @@ -0,0 +1,119 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA divider +------------------------------------------------------------------------------- +-- architecture for a bit-serial divider +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; + +architecture behaviour of divider is + +signal reg_busy : std_logic; +signal reg_denom : std_logic_vector(2*width-2 downto 0); +signal reg_remain : std_logic_vector(width-1 downto 0); +signal reg_quotient : std_logic_vector(width-1 downto 0); +signal reg_hotbit : std_logic_vector(width-1 downto 0); + +signal next_busy : std_logic; +signal next_denom : std_logic_vector(2*width-2 downto 0); +signal next_remain : std_logic_vector(width-1 downto 0); +signal next_quotient : std_logic_vector(width-1 downto 0); +signal next_hotbit : std_logic_vector(width-1 downto 0); + +begin -- behaviour + + busy <= reg_busy; + quotient <= reg_quotient; + remain <= reg_remain; + + syn_proc: process (clock, reset) + begin -- process sync + + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + + reg_busy <= '0'; + reg_denom <= (others => '0'); + reg_remain <= (others => '0'); + reg_quotient <= (others => '0'); + reg_hotbit <= (others => '0'); + reg_hotbit(0) <= '1'; + + elsif clock'event and clock = '1' then -- rising clock edge + + if trigger = '1' then + reg_denom(2*width-2 downto width-1) <= denom; + reg_denom(width-2 downto 0) <= (others => '0'); + reg_remain <= numer; + reg_quotient <= (others => '0'); + reg_hotbit(width-1) <= '1'; + reg_hotbit(width-2 downto 0) <= (others => '0'); + if zero(denom) = '1' then + exc <= '1'; + reg_busy <= '0'; + else + exc <= '0'; + reg_busy <= '1'; + end if; + else + reg_denom <= next_denom; + reg_remain <= next_remain; + reg_quotient <= next_quotient; + reg_hotbit <= next_hotbit; + reg_busy <= next_busy; + exc <= '0'; + end if; + + end if; + end process syn_proc; + + compute: process (reg_denom, reg_remain, reg_quotient, reg_hotbit) + variable tmp_remain : std_logic_vector(2*width-2 downto 0); + begin -- process compute + + next_denom <= '0' & reg_denom(2*width-2 downto 1); + next_remain <= reg_remain; + next_quotient <= reg_quotient; + next_hotbit <= '0' & reg_hotbit(width-1 downto 1); + + if reg_hotbit(0) = '1' then + next_hotbit <= reg_hotbit; + next_busy <= '0'; + else + next_busy <= '1'; + end if; + + tmp_remain := std_logic_vector(resize(unsigned(reg_remain), 2*width-1) - unsigned(reg_denom)); + if tmp_remain(2*width-2) = '0' then + next_remain <= tmp_remain(width-1 downto 0); + next_quotient <= reg_quotient or reg_hotbit; + end if; + + end process compute; + +end behaviour; Index: trunk/vhdl/alu_ent.vhd =================================================================== --- trunk/vhdl/alu_ent.vhd (nonexistent) +++ trunk/vhdl/alu_ent.vhd (revision 2) @@ -0,0 +1,56 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA ALU +------------------------------------------------------------------------------- +-- entity for the ALU +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity alu is + + port ( + clock : in std_logic; + reset : in std_logic; + + op : in ALU_OP; + + a : in std_logic_vector(REG_WIDTH-1 downto 0); + b : in std_logic_vector(REG_WIDTH-1 downto 0); + i : in std_logic_vector(REG_WIDTH-1 downto 0); + pc : in std_logic_vector(REG_WIDTH-1 downto 0); + + intr : in std_logic; + + exc : out std_logic; + + iena : out std_logic; + pcchg : out std_logic; + busy : out std_logic; + result : out std_logic_vector(REG_WIDTH-1 downto 0)); + +end alu; Index: trunk/vhdl/marca_ent.vhd =================================================================== --- trunk/vhdl/marca_ent.vhd (nonexistent) +++ trunk/vhdl/marca_ent.vhd (revision 2) @@ -0,0 +1,42 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA top level entity +------------------------------------------------------------------------------- +-- entity definition for the processor itself +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity marca is + + port ( + clock : in std_logic; + ext_reset : in std_logic; + ext_in : in std_logic_vector(IN_BITS-1 downto 0); + ext_out : out std_logic_vector(OUT_BITS-1 downto 0)); + +end marca; Index: trunk/vhdl/fetch.vhd =================================================================== --- trunk/vhdl/fetch.vhd (nonexistent) +++ trunk/vhdl/fetch.vhd (revision 2) @@ -0,0 +1,121 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA fetch stage +------------------------------------------------------------------------------- +-- architecture for the instruction-fetch pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.marca_pkg.all; + +architecture behaviour of fetch is + +component code_memory + generic ( + init_file : string); + port ( + clken : in std_logic; + clock : in std_logic; + address : in std_logic_vector (PADDR_WIDTH-1 downto 0); + q : out std_logic_vector (PDATA_WIDTH-1 downto 0)); +end component; + +signal enable : std_logic; + +signal address : std_logic_vector(PADDR_WIDTH-1 downto 0); +signal data : std_logic_vector(PDATA_WIDTH-1 downto 0); + +signal pc_reg : std_logic_vector(REG_WIDTH-1 downto 0); +signal next_pc : std_logic_vector(REG_WIDTH-1 downto 0); + +signal next_pc_out : std_logic_vector(REG_WIDTH-1 downto 0); + +begin -- behaviour + + enable <= not hold; + pc_out <= pc_reg; + + code_memory_unit : code_memory + generic map ( + init_file => "../vhdl/code.mif") + port map ( + address => address(PADDR_WIDTH-1 downto 0), + clken => enable, + clock => clock, + q => data); + + syn_proc: process (clock, reset) + begin -- process syn_proc + if reset = RESET_ACTIVE then -- asynchronous reset (active low) + pc_reg <= (others => '0'); + elsif clock'event and clock = '1' then -- rising clock edge + if hold = '0' then + pc_reg <= next_pc; + end if; + end if; + end process syn_proc; + + increment: process (pc_reg, pc_in, pcena, data) + begin -- process increment + if pcena = '1' then + next_pc <= pc_in; + else + -- "predict" hard branches + if data(PDATA_WIDTH-1 downto PDATA_WIDTH-8) = OPC_PFX_C & OPC_BR then + next_pc <= std_logic_vector(signed(pc_reg) + signed(data(7 downto 0))); + else + next_pc <= std_logic_vector(unsigned(pc_reg) + 1); + end if; + end if; + end process increment; + + forward: process (pc_reg, pc_in, pcena, data, reset) + begin -- process forward + if reset = RESET_ACTIVE then + address <= (others => '0'); + else + if pcena = '1' then + address <= pc_in(PADDR_WIDTH-1 downto 0); + else + if data(PDATA_WIDTH-1 downto PDATA_WIDTH-8) = OPC_PFX_C & OPC_BR then + address <= std_logic_vector(signed(pc_reg) + signed(data(7 downto 0)))(PADDR_WIDTH-1 downto 0); + else + address <= std_logic_vector(unsigned(pc_reg) + 1)(PADDR_WIDTH-1 downto 0); + end if; + end if; + end if; + end process forward; + + spread: process (data) + begin -- process spread + src1 <= data(3 downto 0); + src2 <= data(7 downto 4); + dest <= data(11 downto 8); + instr <= data; + end process spread; + +end behaviour; Index: trunk/vhdl/decode_ent.vhd =================================================================== --- trunk/vhdl/decode_ent.vhd (nonexistent) +++ trunk/vhdl/decode_ent.vhd (revision 2) @@ -0,0 +1,71 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA decode stage +------------------------------------------------------------------------------- +-- entity definition for the instruction-decode pipeline stage +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity decode is + + port ( + clock : in std_logic; + reset : in std_logic; + + hold : in std_logic; + stall : in std_logic; + + pc_in : in std_logic_vector(REG_WIDTH-1 downto 0); + pc_out : out std_logic_vector(REG_WIDTH-1 downto 0); + + instr : in std_logic_vector(PDATA_WIDTH-1 downto 0); + + src1_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + src1_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + src2_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + src2_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + + dest_in : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + dest_out : out std_logic_vector(REG_COUNT_LOG-1 downto 0); + + aop : out ALU_OP; + mop : out MEM_OP; + iop : out INTR_OP; + + op1 : out std_logic_vector(REG_WIDTH-1 downto 0); + op2 : out std_logic_vector(REG_WIDTH-1 downto 0); + imm : out std_logic_vector(REG_WIDTH-1 downto 0); + + unit : out UNIT_SELECTOR; + target : out TARGET_SELECTOR; + + wr_ena : in std_logic; + wr_dest : in std_logic_vector(REG_COUNT_LOG-1 downto 0); + wr_val : in std_logic_vector(REG_WIDTH-1 downto 0)); + +end decode; Index: trunk/vhdl/divider_ent.vhd =================================================================== --- trunk/vhdl/divider_ent.vhd (nonexistent) +++ trunk/vhdl/divider_ent.vhd (revision 2) @@ -0,0 +1,50 @@ +-- This file is part of the marca processor. +-- Copyright (C) 2007 Wolfgang Puffitsch + +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU Library General Public License as published +-- by the Free Software Foundation; either version 2, or (at your option) +-- any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Library General Public License for more details. + +-- You should have received a copy of the GNU Library General Public +-- License along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +------------------------------------------------------------------------------- +-- MARCA divider +------------------------------------------------------------------------------- +-- entity of a bit-serial divider +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Wolfgang Puffitsch +-- Computer Architecture Lab, Group 3 +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +use work.marca_pkg.all; + +entity divider is + + generic ( + width : integer := REG_WIDTH); + + port ( + clock : in std_logic; + reset : in std_logic; + trigger : in std_logic; + denom : in std_logic_vector(width-1 downto 0); + numer : in std_logic_vector(width-1 downto 0); + exc : out std_logic; + busy : out std_logic; + quotient : out std_logic_vector(width-1 downto 0); + remain : out std_logic_vector(width-1 downto 0)); + +end divider;

powered by: WebSVN 2.1.0

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