• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

t/H07-May-2022-680561

COPYINGH A D03-May-202217.9 KiB350287

MakefileH A D03-May-2022583 2913

NEWSH A D03-May-20221.5 KiB4328

READMEH A D03-May-202212.4 KiB338239

asm.cH A D03-May-202216.2 KiB665354

asm.hH A D03-May-20222.4 KiB10560

bench.shH A D03-May-2022485 1110

changelogH A D03-May-2022924 2319

exhaust.cH A D03-May-202211.9 KiB543377

exhaust.hH A D03-May-20221.6 KiB7932

fixed.rcH A D03-May-20223.6 KiB103101

imp.rcH A D03-May-202213 21

insn.hH A D03-May-20222.9 KiB15066

jaguar.rcH A D03-May-20223.6 KiB103101

npaper2.rcH A D03-May-20223.6 KiB103101

pspace.cH A D03-May-20221 KiB6960

pspace.hH A D03-May-2022934 4016

sim.cH A D03-May-202232.9 KiB1,269787

sim.hH A D03-May-2022940 4520

spl.rcH A D03-May-2022104 98

stalker.rcH A D03-May-2022432 1412

test.plH A D03-May-20221.6 KiB6949

README

1$Id: README,v 1.1 2003/06/06 12:08:39 martinus Exp $
2
3This is exhaust version 1.9, a memory array redcode simulator.  It is
4mostly in the public domain (see the file COPYING for details).
5
6Files:
7        changelog          Log of Change.
8        COPYING            lack of license.
9        Makefile           file for make.
10        README             This file.
11	NEWS		   Notes about things that might break.
12        asm.c              (Dis)Assembler.
13        asm.h              Token codes and prototypes for assembler.
14        exhaust.c          Simplified pMARS-like simulator.
15        exhaust.h          Global constants, structures and types.
16        insn.h             Instruction encoding specs.
17        sim.c              Simulator proper.
18        sim.h              Simulator prototypes.
19	pspace.c	   P-space implementation.
20	pspace.h	   P-space prototypes.
21        test.pl            Perl program to test for differences between
22                           simulators.
23        t/*.red		   Redcode for tests.
24	t/*.rc		   Load files for tests.
25
26To compile on UNIX or on DOS with djgpp first edit the makefile to
27your comfort and then run `make' to get an executable `exhaust'.  If
28you have gcc you hopefully don't need to make any makefile
29modifications.  See the section `How to use the simulator and friends'
30below for an overview of how to use the simulator in your programs.
31
32Thanks to the pMARS authors and Ken Espiritu for ideas implemented in
33this simulator.  Especially Ken's effective addressing calculation code
34from pMARS 0.8.6 was adapted for a great speed-up.
35
36
37* How to use the simulator and friends
38--------------------------------------
39
40This is a quick run-down on how to use the simulator and assembler
41with your program.  Special considerations for P-Space are detailed in
42the section about p-space below, so here non-P warriors are assumed.
43After munging your source file, remember to link your executable with
44sim.o, pspace.o, and asm.o!  You don't need asm.o if you don't use the
45assembler or disassembler.
46
47The main things that you should do are:
48  - generate (perhaps by assembling) the warrior code
49  - allocate the internal buffers
50  - clear core and load the warriors into it
51  - call the simulator to do it's thing
52
53In the examples, I assume you use a warrior structure similar to
54exhaust.h's struct warrior_st, but it is not canonical in any way.
55Here I rely on the following fields:
56
57        insn_t code[ MAXLENGTH ];   /* code of warrior */
58        int len;                    /* length of warrior code */
59        int start;                  /* start relative to first insn */
60
61* The assembler:
62
63i) You need some declarations and includes:
64
65#include "exhaust.h"
66#include "asm.h"
67
68        warrior_t w1, w2;       /* warrior structs hold code and misc. info */
69        int CORESIZE = 8000,    /* size of core */
70            PROCESSES = 8000,   /* max. number of processes per warrior */
71            NWARRIORS = 2,      /* number of warriors */
72            CYCLES = 80000;     /* cycles until tie */
73
74ii) Then you want to assemble your warriors, say aeka and Rave:
75
76        asm_fname( "aeka.rc", &w1, CORESIZE );
77        asm_fname( "rave.rc", &w2, CORESIZE );
78
79You could also use asm_file(FILE *, warrior_t *, CORESIZE) to assemble
80from a stream.
81
82
83* Simulator:
84
85i) The simulator interface is simple.  First you need to allocate and
86query the address of the core memory:
87
88#include "exhaust.h"
89#include "sim.h"
90        insn_t *core;
91
92        core = sim_alloc_bufs( NWARRIORS, CORESIZE, PROCESSES, CYCLES );
93
94If any of the allocations failed the returned value will be NULL.  You
95should check for that. When you're done with the core memory and other
96buffers, call sim_free_bufs(void), but note that sim_alloc_bufs()
97frees any memory it previously allocated.  i.e. you can successively
98call it without intervening calls to sim_free_bufs().
99
100For backward compatibility you can also use use sim() as follows to
101allocate with the default CORESIZE=PROCESSES=8000:
102
103        (void) sim( -1, 0, 0, CYCLES, &core );
104
105ii) Then you clear core and load the warriors:
106
107        memset( core, 0, sizeof(insn_t) * CORESIZE );
108or
109	sim_clear_core();
110
111and
112	sim_load_warrior(0,   &(w1.code[0]), w1.len );
113	sim_load_warrior(pos, &(w2.code[0]), w2.len );
114
115where `pos' is the core address where you want to load w2.  This
116differs slightly from the previous release where you had to:
117
118        memcpy( core,       w1.code, sizeof(insn_t) * w1.len );
119        memcpy( core + pos, w2.code, sizeof(insn_t) * w2.len );
120
121You can still do that.  (Note however, that the flags field of
122instructions should be cleared as the simulator won't do it.
123sim_load_warrior() does this for you.)
124
125
126iii) Right, now you're ready to fight.  If you have only one or two
127warriors, you can use sim():
128
129        result = sim( 2, w1.start, (w2.start+pos)%CORESIZE, CYCLES, NULL);
130
131The result is 0 if w1 won, 1 if w2 won, and 2 on a tie (-1 if the
132simulator panics).
133
134For multi-warrior battles with more than two warriors you need
135some extra declarations:
136
137        field_t war_pos_tab[ NWAR ];    /* a table of core addresses
138                                         * that specify where the warriors
139                                         * start their execution. */
140        int death_tab[ NWAR ];          /* the simulator stores the
141                                         * results here. (see below) */
142
143Then allocate the buffers and obtain the core address using
144sim_alloc_bufs(), clear the core, and load the warriors into it as
145before.  Save the positions where you loaded the warriors into
146war_pos_tab[].  Now you're ready to fight, so call sim_mw():
147
148        int alive_cnt;
149        alive_cnt = sim_mw( NWAR, war_pos_tab, death_tab );
150
151The return value is the number of warriors alive at the end of the
152round.  Dead warriors are recorded into death_tab[] by order of death.
153i.e. death_tab[0] contains the index of the first warrior to die,
154death_tab[1] the index of the second to go, and so on.
155
156
157* The disassembler:
158
159If you want to disassemble an instruction use dis1() or discore() from
160asm.c.  Examples:
161
162#include "exhaust.h"
163#include "asm.h"
164
165        char str[60];
166        insn_t instr;
167
168        instr.in = _OP( SPL, mF, DIRECT, BPREDEC );
169        instr.a = instr.b = 0;
170        core[1234] = instr;
171
172        dis1( str, core[1234], CORESIZE ); printf("%s\n", str);
173        dis1( str, instr, CORESIZE );      printf("%s\n", str);
174
175                                        /* disassemble addresses 5..14 */
176        discore( core, 5, 15, CORESIZE);/* and print to stdout. */
177
178
179* P-Space
180---------
181
182The simulator interface is oriented toward playing single battles, but
183p-space by its nature requires a multi-round interface.  Hence there
184are some complications when playing p-space warriors.  The main change
185for P-spacer battles over normal ones is that you need to pair
186p-spaces to warriors.  Also, if you are running multiple battles you
187need to reinitialise the p-spaces between each battle.
188
189The basic model is simple: the simulator maintains an array of
190NWARRIORS p-spaces that you may manipulate.  The ith p-space in this
191array always corresponds to the ith warrior passed to sim() or
192sim_mw(), so that the first warrior always accesses the first p-space,
193the second the second, and so on.  The pairing betweens p-spaces and
194warriors is up to you.  After each round the p-space location 0 of
195each warrior is updated with either a) zero if the warrior died or b)
196the number of warriors alive at the end of the battle.
197
198[A note about naming conventions: pspace_XXX() functions are mostly
199local in nature -- they refer only to their argument p-spaces.  The
200sim_XXX_pspace() functions are about the collection of p-spaces
201maintained by the simulator.]
202
203
204* Accessing p-spaces
205
206To get a pointer to the ith p-space you use the function
207sim_get_pspace():
208
209	pspace_t *p = sim_get_pspace(i);
210
211Then to access the cells of `p', use the functions pspace_get() and
212pspace_set():
213
214	contents_of_cell_123 = pspace_get(p, 123);
215
216	pspace_set(p, 123, new_contents);
217
218
219* P-space initialisation; resets
220
221 - The size of p-space is specified at memory allocation time using
222   the function sim_alloc_bufs2().  It is exactly like
223   sim_alloc_bufs(), except it takes as an additional parameter the
224   size of pspace, which must be positive.  The later function
225   defaults p-space to CORESIZE/16 cells, so you don't need to change
226   it.
227
228 - The function sim_clear_pspaces() clears the p-spaces of all warriors
229   and stores CORESIZE-1 into their p-space location 0.  P-Space is
230   cleared on allocation, so you only need to call this function
231   between battles, but not rounds.  This function doesn't change
232   the sharing status of p-spaces.
233
234 - To completely reinitialise p-spaces and to make p-spaces of each
235   warrior private again, call the sim_reset_pspaces() function.  This
236   also calls sim_clear_pspaces().
237
238
239* Pairing p-spaces to warriors
240
241If you are changing the order in which warriors execute within each
242cycle on a per-round basis, you need to order p-spaces as well.  For
243example, pMARS cyclically permutes the order of warriors so that every
244even round the first warrior executes first in each cycle, and every
245odd round the second warrior executes first.  With non-pspace warriors
246you only need to give the starting positions of the warriors in the
247`war_pos_tab[]' argument in the order you want the warriors to
248execute, but with p-warriors involved you need to match p-spaces to
249warriors as well.
250
251 - The simulator maintains an array of pointers to p-space structures,
252   one for each warrior.  The ith p-space structure corresponds to the
253   ith warrior in the `war_pos_tab[]' array argument of warrior
254   starting positions passed to sim_mw().  Similarly for the two
255   warriors given to the sim() function.  You need to order this array
256   of pointers to match the order in which you are passing warrior
257   starting positions to the simulator.
258
259   To access the array, use sim_get_pspaces():
260
261	pspace_t **pspaces;
262	pspaces = sim_get_pspaces();
263
264	// now permute the pointers in the pspaces array into the
265	// same order as your warriors.
266	...
267
268   Of course, if you are not changing the order in which warriors
269   execute on a per-round basis, you don't need to permute the pspaces
270   array.  This may be suitable in some cases.
271
272
273* Sharing p-spaces
274
275There is only minimal support for PINs and p-space sharing in that the
276assembler understands the `PIN' pseudo-op, but you must match PINs to
277p-spaces yourself.
278
279  - The warrior structure warrior_st in exhaust.h needs the extra fields
280
281	int have_pin;			// boolean: is field `pin' valid?
282	u32_t pin;			// PIN of warrior, possibly.
283
284    that are used when assembling from files/streams.  The interface
285    to asm_line() has changed accordingly so it can identify and
286    return the PIN pseudo-op.
287
288  - To share p-spaces of two warriors, you need to call the function
289    pspace_share(p1, p2) for two pointers p1, p2 to p-spaces.  The
290    contents of p-space p1 becomes the contents of the shared p-space.
291    P-space location 0 is never shared.
292
293  - The function pspace_privatise(p) resets the p-space p to be
294    private.  The contents of p1 are then undefined.
295
296
297
298* Files that the assembler eats
299-------------------------------
300
301In short: the load files that the '94 draft specifies are accepted.
302Specifically, the files may contain only `;' comments, white space,
303instructions, and pseudo-ops.  The instructions must follow this form:
304
305  [opt START label]    OPCODE.MODIFIER  MODE integer , MODE integer
306
307Various idiosyncrasies:
308
309 - You can't implicitly specify direct addressing mode by dropping `$'.
310
311 - The start of a warrior is determined by the last seen appearance of
312   the START label or `ORG'.  Of the pseudo-ops using `END label' or
313   `ORG label' aren't supported; only `ORG integer' is.
314
315 - `END' stops warrior assembly.  You still can assemble from the
316   same file or stream another warrior that follows though.
317
318 - special KotH comments aren't recognised.
319
320To support using pMARS as an assembler any line that begins with
321`Program' is ignored.  So you could first say
322
323  pmars -r 0 Fancy_Source.red >Simple_Source.rc
324
325and then use the asm.c assembler to import Simple_Source.rc into your
326program.  Note that pmars doesn't output PINs of warriors.
327
328
329* When the simulator crashes
330----------------------------
331
332... or is just plain wrong by producing incorrect results please tell
333me about it at the address given below.  Ditto for the assembler or
334anything else in these files.  I'd appreciate a simple test case that
335illustrates the bug if possible.
336
337The author can be reached by email at: jpihlaja@cc.helsinki.fi
338