v50 Steam/Premium information for editors
  • v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
  • Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.

Editing User:Vasiln/Goblin Logic 2

Jump to navigation Jump to search

Warning: You are not logged in.
Your IP address will be recorded in this page's edit history.


The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

Latest revision Your text
Line 379: Line 379:
 
If (end(2) OR (propagate(2) AND NOT (generate(1) OR (propagate(1) AND generate(0))) then carry(3):=0
 
If (end(2) OR (propagate(2) AND NOT (generate(1) OR (propagate(1) AND generate(0))) then carry(3):=0
  
Let's test our logic:
+
Just for shits and giggles, let's spell out the carry bit for carry(9)-- 8-bit words.
 
  a      011
 
  b      010
 
(add    0101)
 
  XOR->a  001
 
  carry  egp
 
  LCU->b 0100
 
  a      001
 
  XOR    101
 
(carry  pep)
 
(LCU    0000)
 
 
 
Perfect. 
 
 
 
 
 
Just for fun, let's spell out the carry bit for carry(9)-- 8-bit words.
 
  
 
If generate(8) OR (propagate(8) AND (generate(7) OR (propagate(7) AND (generate(6) OR (propagate(6) AND (generate(5) OR (propagate(5) AND (generate(4) OR (propagate(4) AND (generate(3) OR (propagate(3) AND (generate(2) OR (propagate(2) AND (generate(1) OR (propagate(1) AND generate (0) (with a whole mess of closing delimiters here) then carry(9):=1
 
If generate(8) OR (propagate(8) AND (generate(7) OR (propagate(7) AND (generate(6) OR (propagate(6) AND (generate(5) OR (propagate(5) AND (generate(4) OR (propagate(4) AND (generate(3) OR (propagate(3) AND (generate(2) OR (propagate(2) AND (generate(1) OR (propagate(1) AND generate (0) (with a whole mess of closing delimiters here) then carry(9):=1
Line 401: Line 385:
 
If end(8) OR (propagate(8) AND NOT (generate(7) OR (propagate(7) AND NOT (generate(6) OR (propagate(6) AND NOT (generate(5) OR (propagate(5) AND NOT (generate(4) OR (propagate(4) AND NOT (generate(3) OR (propagate(3) AND NOT (generate(2) OR (propagate(2) AND NOT (generate(1) OR (propagate(1) AND NOT generate (0) (with a whole mess of closing delimiters here) then carry(9):=0
 
If end(8) OR (propagate(8) AND NOT (generate(7) OR (propagate(7) AND NOT (generate(6) OR (propagate(6) AND NOT (generate(5) OR (propagate(5) AND NOT (generate(4) OR (propagate(4) AND NOT (generate(3) OR (propagate(3) AND NOT (generate(2) OR (propagate(2) AND NOT (generate(1) OR (propagate(1) AND NOT generate (0) (with a whole mess of closing delimiters here) then carry(9):=0
  
What an ugly mess.  I think you can see why I didn't want to have to design this.  However, I think it's clear how to extend the technique to any bit length.
+
What an ugly fucking mess.  I think you can see why I didn't want to have to design this.  However, I think it's clear how to extend the technique to any bit length.
  
  
Line 437: Line 421:
 
   ##d#d ##    propagate(6) AND generate(5)
 
   ##d#d ##    propagate(6) AND generate(5)
 
  ## ### ##    OR
 
  ## ### ##    OR
  # #d  #1#    generate(6)                                            carry(7):=1
+
  # #d  #1#    generate(6)                                            carry(2):=1
 
  r########
 
  r########
  
 
Max length, 26 steps.  LCU(8) would for 30 steps.  ~365 ticks.  XOR, LCU, XOR for 8-bit add in less than 600 ticks, whereas the parallel ripple add would take us 1600.  Total size, 29x10x1, plus infrastructure.
 
Max length, 26 steps.  LCU(8) would for 30 steps.  ~365 ticks.  XOR, LCU, XOR for 8-bit add in less than 600 ticks, whereas the parallel ripple add would take us 1600.  Total size, 29x10x1, plus infrastructure.
  
Let's do an 8-bit test:
+
The really cool thing about this operation is that it generates a word that, when added to the original addition, generates NO carries. So when we do our second XOR, LCU(x)=0, for any x.
 
 
  a       10110010
 
  b      011011011
 
  (add    110001101)
 
  XOR->a  01101001
 
  carry    gppgpegp
 
  LCU->b  111100100
 
  a        01101001
 
  XOR      10001101
 
(carry    pggeppep)
 
(LCU    111000000)
 
 
 
What do you know?  It works!
 
  
 
===Operation 0101: XOR with LCU===
 
===Operation 0101: XOR with LCU===
Line 467: Line 438:
 
Of course, we need to get our inputs in, and outputs out.
 
Of course, we need to get our inputs in, and outputs out.
  
* Operation 0001: Write from memory to register a, takes memory address as argument
+
Operation 0001: Write from memory to register a
 
+
Operation 0010: Write from memory to register b
* Operation 0010: Write from memory to register b, takes memory address as argument
+
Operation 0011: Write from register a to memory
 
 
Remember, register b is a 9 bit value-- so our writes to memory will only write the first 8 bits of b.
 
 
 
* Operation 0011: Write from register a to memory, takes memory address as argument
 
 
 
In reality, these operations will consist of an intermediary step-- writing to the buffer.  Since we're now working with 8-bit words and 4-bit addresses, and these are 4-bit instructions, we can now specify a memory address to read from or write to.  Notice that our XOR doesn't take any argument at all-- it always works on the same two registers.  That's fine for now.  In the future, we can expand the operation to single-instruction add, add with carry, AND, OR, NOR-- anything our heart desires.
 
 
 
Here's a sequence of instructions to add two numbers and output the result to a memory cell.
 
  
  0000  00010101  Load value in 0101 into register a
+
In reality, these operations will consist of an intermediary step-- writing to the bufferSince we're now working with 8-bit words and 4-bit addresses, and these are 4-bit instructions, we can now specify a memory address to read from or write to.
  0001  00100110  Load value in 0110 into register b
 
  0010  01010000  XOR a and b->a, carry->b
 
  0011  01010000  XOR a and b->a, (carry->b)
 
  0100  00110111  Write value in register a into 0111
 
  0101  xxxxxxxx  Operand 1
 
  0110  xxxxxxxx  Operand 2
 
  0111  xxxxxxxx  Output
 
 
 
Addresses 0101, 0110, and 0111 are assumed to be data cells.  This program will add the value in 0101 to the value in 0110 and output the result to 0111Notice that we called XOR twice, and that the "0000" argument for it is both arbitrary and meaningless.  In fact, because XOR is working only on predefined registers, we could use that argument to space to make 16 different commands, all with the same instruction set.
 
 
 
Note that in reality, what will happen is that our program will add the two values-- and then try to evaluate 0101 as an instruction.  We'll get to that later.  Also note that 16 words are not very many!  Just adding two numbers required 8 words.  One more thing to pay attention to: our create carry circuit will always function AFTER our XOR, so we don't need to worry about writing to register b from that circuit at the same time that we're reading from that circuit to do an XOR. That's very important!
 
  
 
But wait a minute.  What if we want to add larger numbers?  Numbers too large to be expressed in 8 bits?  We've broken our carry functionality by our redesign.  We need a way to access LCU(8).
 
But wait a minute.  What if we want to add larger numbers?  Numbers too large to be expressed in 8 bits?  We've broken our carry functionality by our redesign.  We need a way to access LCU(8).
  
===Operation 0110: Arithmetic right shift on register b, takes number of shifts as argument===
+
===Operation 0110: Arithmetic right shift===
  
What we can do is shift LCU right 8 times!  We'll move the value of each bit from x to x-8, and fill in the blank spaces with zeroes.  So LCU=100110000 -> LCU=000000001, and we can XOR it with the next value to carry the one from an earlier addition.
+
What we can do is shift LCU right 8 times!  We'll move the value of each bit from x to x-8, and fill in the blank spaces with zeroes.  So LCU=100000000 -> LCU=000000001, and we can XOR it with the next value to carry the one from an earlier addition.
  
But arithmetic right shift is a really useful function for other stuff too.  For instance, right shifting 1 space is equivalent to dividing a number by two and dropping the remainder.  We'll make it so that arithmetic right shift operates on register b, and takes an argument in the last four bits specifying the number of bits to shift.  Since 0000=0 shifts, which is totally useless, we'll make an argument of 0000 shift it 8 times, rather than zero times; and since we might want to use this for other functions, we'll make shifts of fewer than 8 drop the 9th bit (read in 0s instead).  That way, we can also use this to create an XOR word for writing to specific bits.
+
But arithmetic right shift is a really useful function for other stuff too.  We'll make it so that arithmetic right shift operates on register b, and takes an argument in the last four bits specifying the number of bits to shift.  Since 0000=0 shifts, which is totally useless, we'll make an argument of 0000 shift it 8 times, rather than zero times; and since we might want to use this for other functions, we'll make shifts of fewer than 8 drop the 9th bit (read in 0s instead).  That way, we can also use this to create an XOR word for toggling output memory.
  
 
Of course, we'll need to be able to save the LCU value to be able to do this.
 
Of course, we'll need to be able to save the LCU value to be able to do this.
  
* Operation 0100: Write from register b to memory, takes memory address as argument
+
Operation 0100: Write from register b to memory
 
 
Again, remember that register b is 9 bits big, so when we write to register b, we'll only write the first 8 bits, and fill in the 9th with a zero.
 
 
 
We'll want a left shift as well, and we might want to do a bit rotate too.  A left shift is just like a right shift but in reverse.  So a left shift by one multiplies a number by 2 (so long as we don't overflow our bit space!) So we can do this by adding a number to itself.  A right-hand bit rotate is just like a right shift, except it doesn't write in zeroes on the right hand side-- for instance, 101, rotated once to the right, stays 101, and 001 becomes 100.  Since there's no possible reason to want to do this with our carry bit, we'll ignore the 9th bit of b for our rotate.
 
 
 
Operation 0111: Right-hand bit rotate, takes number of shifts as argument
 
 
 
Again, notice that 0111000-01111111 are going to be a useless instructions-- here's 8 more places we can cram in more instructions if we need to.
 
 
 
Between right hand bit rotate and right-hand shift, we can do any left hand operations.  To left-hand rotate, simply right hand rotate in 8's complement-- that is, rotate it 7 times to shift it once to the left, rotate it 6 times to shift it twice to the left.  To do a left hand arithmetic shift of n units, first rotate it right 8-n units, rightshift it n units, then right rotate it 8-n units again.
 
 
 
We don't actually need bit shifts and rotates to be turing complete (we can reach them via additions), but we do need add with carry, and bitshift is how our architecture is going to get there.  Here's a program that adds two two-word (16 bit) values and outputs the result to a third, 2-word, space.
 
 
 
  0001  xxxxxxxx  Operand 1 (*256)
 
  0010  xxxxxxxx  Operand 1 (*1)
 
  0011  xxxxxxxx  Operand 2 (*256)
 
  0100  xxxxxxxx  Operand 2 (*1)
 
  0101  xxxxxxxx  Carry variable
 
  0110  xxxxxxxx  Output(*256)
 
  0111  xxxxxxxx  Output(*1)
 
  1000  00010010  Load 0010 into a
 
  1001  00100100  Load 0100 into b
 
  1010  01010000  XOR->a, carry->b
 
  1011  00110111  Write a into 0111
 
  1100  01000101  Write b into 0101
 
  1101  01100000  Right shift b 8 times
 
  1110  00010001  Load 0001 into a
 
  1111  01010000  XOR->a, carry->b
 
  0000  01010000  XOR->a, (carry->b) Carry will be ignored
 
  0001  00100011  Load 0011 into b
 
  0010  01010000  XOR->a, carry->b
 
  0011  01010000  XOR->a, (carry->b)  Carry will be ignored
 
  0100  00110110  Write a to 0110
 
  0101  00010111  Load 0111 into a
 
  0110  00100101  Load 0101 into b
 
  0111  01010000  XOR->a, (carry->b)  Carry will be ignored
 
  1000  00110111  Write a into 0111
 
 
 
You can see that we've already exceeded our 16 bits-- our program and data wraps around.  You can also see that this is an inefficient way to do an add with carry-- it involves a lot of writes to memory.  Adding more instructions, or parameters to our existing XOR, could reduce the number of times we need to swap memory around.  But it works, and we're not anticipating doing any adds with carry.  We just want the capability.  In this program, I've located the data earlier in memory than our instructions.  It really doesn't matter where stuff goes, but our instructions are going to be executed sequentially, so we want all of our instructions in one block separate from our data-- at least, for now.
 
 
 
Bit shifting and bit rotation is simple in our heads, but in our fortresses, it's going to be complex.  For each bit (and we have 9), we need 15 paths: write true and false to any of the other 7 bit locations, as well as a null path for writing to self.  Additionally, since our shifts and rotates write to the same register they read from, we need intermediate memory-- we need to write to buffer, then, from there, write to register b.  It's going to take up a lot of space.
 
 
 
Here's the circuit for ARS(8) (arithmetic right shift, position 8-- position 8 is actually our ninth bit of register b):
 
 
 
      ####
 
  ######h1#                                              and b(8) is 0, write 0 to b(0)
 
  #hhhhd###    If argument is 0000 and mode is bit shift
 
  r#####d2#                                              and b(8) is 1, write 1 to b(0)
 
  # d#3####
 
  # d ##
 
  # d #        If argument is not 0000 or mode is not bit shift, don't write anything anyplace.
 
  # d #
 
  ##h##
 
  ###
 
 
 
 
 
Here's part of the circuit for RS(0)  (arithmetic right shift or right rotate, position 0)
 
 
 
 
 
  ###  ####
 
  ## ####d1#                                          and mode is bit shift, write 0 to buffer(7)
 
  #h#hhhd####    Argument is 0001 (shift 1 place to b(7))
 
  r######hh2#                                        and mode is bit rotate  and b(0) is false  write 0 to buffer(7)
 
      #d###                                                                and b(0) is true
 
      #3#                                                                                      write 1 to buffer(7)
 
      ###
 
 
 
But bit shifts are going to write on higher values of RS.  We take 8 arguments (0000, or >0111, return null); each non-null argument differentiates between mode; each mode writes a true or a false.  29 arms.  For christ's sake.
 
 
 
  #########
 
  ######d^#                                                                                                                        write 1 to buffer(x-3) for all circuits where x>=3
 
  ##### ###
 
  ####d#h^#
 
  #### #####
 
  #### ##d^#
 
##### # ###
 
###dd#h#h^#                                          And argument(1) is 1 and argument(0) is 1 and mode is bit rotate and b(x)=0, write 0 to buffer(x-3)
 
## ########
 
# ######d^#                                                                                                                      write 1 to buffer(x-2) for all circuits where x>=2
 
# ##### ###
 
# ####d#h^#
 
# ### #####
 
# ### ##d^#
 
# ### # ###
 
# #dh#h#h^#                                          And argument(1) is 1 and argument(0) is 0 and mode is bit rotate and b(x)=0, write 0 to buffer(x-2)
 
# #########                                         
 
# ######d^#                                                                                                          and b(x)=1, write 1 to buffer(x-1) for all circuits where x>=1
 
# ##### ###
 
# ####d#h^#                                                                                    and mode is bit shift and b(x)=0, write 0 to buffer(x-1)
 
# ### #####
 
# ### ##d^#                                                                                                          and b(x)=1, write 1 to buffer(x-1)
 
## ## # ###
 
#h#hd#h#h^#                    And argument(2) is 0 and argument(1) is 0 and argument(0) is 1 and mode is bit rotate and b(x)=0, write 0 to buffer(x-1)
 
#h#########  Argument(3) is 0
 
# hhhh##      Argument is 0000
 
r#####^#                        No write
 
# d  ##      Argument(3) is 1 (argument>0111)
 
#h#########  Argument(3) is 0
 
#d#hh#h#h^#                    And argument(2) is 1 and argument(1) is 0 and argument(0) is 0 and mode is bit rotate and b(x)=0, write 0 to buffer(x-4)
 
## ## # ###
 
# ### #d^##                                                                                                          and b(x)=1, write 1 to buffer(x-4)
 
# ### #####
 
# ####d#h^#                                                                                    and mode is bit shift  and b(x)=0, write 0 to buffer(x-4)
 
# ##### ###
 
# ######d^#                                                                                                          and b(x)=1, write 1 to buffer(x-4) for all circuits where x>=4
 
# #########
 
 
 
Etcetera, etcetera, etcetera.
 
 
 
I told you it was going to be a monster.  Although it's narrow enough, a full bitshift circuit would be 55 tiles long.  Notice that we don't write 1 to buffer(x) when in shift mode and when argument>x.  That means that shift(7) is going to be our largest circuit, and shift(0) can be made smaller-- although not significantly smaller.
 
  
Of course, following our writing of a shifted/rotated b to buffer, we'll have to write buffer back to bWe know how to do that.
+
We'll want a left shift as well, and we might want to do a bit rotate too.  A left shift is just like a right shift but in reverse-- but we can do this by adding a number to itself.  A right-hand bit rotate is just like a right shift, except it doesn't write in zeroes on the right hand sideSince there's no possible reason to want to do this with our LCU, we'll ignore the 9th bit of b.
  
Before we go any further, I want to show you something really cool we can do with an arithmetic shift.  Let's take one of the cells from our last program:
+
Operation 0111: Right-hand bit rotate
 
 
  1000  00010010  Load 0010 into a
 
 
 
What happens if we shift it right 4 times, then left 4 times?  We have 00010000-- which can still be read as an instruction.  Now, the instruction is just "Load 0000 into a."  What if we shift it left 4 times, then right 4 times?  We have 00000010.  It can still be read as an instruction, although we haven't defined 0000 as an instruction.  Now what happens if we take those two values and XOR them?  We have 00010010: exactly what we started out with.  Except we can use that process to assign any instruction to some address, or to assign any address to some instruction.  It's hard to imagine what we might do with that-- it kind of has the whiff of black magic to it.  Very powerful; very dangerous.
 
  
 
There's one thing you might be worried about.  We totally forgot about subtraction!  Before, we had this beautiful memory design that can be used to add or subtract, but now, our system is so complex that nobody knows if we can subtract with it.  Don't worry-- there's another trick we can do to make everything work.
 
There's one thing you might be worried about.  We totally forgot about subtraction!  Before, we had this beautiful memory design that can be used to add or subtract, but now, our system is so complex that nobody knows if we can subtract with it.  Don't worry-- there's another trick we can do to make everything work.
  
===Subtraction: Twos complement===
+
===Operation 1000: Twos complement===
 
 
By changing a number to its two's complement value, we can just add it instead of subtracting it.
 
 
 
What's a two's complement (TC)?  Basically, it's the number you get when you subtract a number from 0.  So in a way, we're generating a negative number.  For instance, with three bit words, the TC of 111 is 001-- summed, they make 000.  So instead of subtracting 1 from a 3 bit word, we can just add 111.  Don't believe me?  Try it out:
 
 
 
  010
 
-001
 
  001
 
 
 
  010
 
  +111
 
(1)001
 
 
 
See that carry?  We'll need to invert it for subtracting multiple bits.  That's easy-- we can just XOR it with a 1.
 
 
 
TC of 010 is 110.
 
 
 
    001
 
  -010
 
(1)111
 
 
 
    001
 
  +110
 
(0)111
 
 
 
For numbers that span multiple words (subtracting number cd from ab), we add a to TCc, XOR the carry with 1 (or with 00000001, for 8 bit words), TC the XORed carry, add the TCed XORed carry to b, then add b to TCd.
 
 
 
But how do we make the TC?  We invert each bit, then add 1 to the final value.  I just told you how to invert it-- XOR with 1 (or with 11111111).  We know how to add, right?
 
 
 
So here's our program to subtract:
 
 
 
  0000 00000001 (constant value)
 
  0001 11111111 (constant value)
 
  0010 xxxxxxxx operand 1 (minuend)
 
  0011 xxxxxxxx operand 2(subtrahend)
 
  0100 xxxxxxxx output (difference)
 
  0101 00010011 Load 0011 into a
 
  0111 00100001 Load 0001 into b
 
  1000 01010000 XOR a and b (carry->b)      we drop the carry here, don't care about it
 
  1001 00100000 Load 0000 into b
 
  1010 01010000 XOR a and b (carry->b)
 
  1011 01010000 XOR a and b
 
  1100 00100010 Load 0010 into b
 
  1101 01010000 XOR a and b (carry->b)
 
  1110 01010000 XOR a and b
 
  1111 00110100 Write a to 0100
 
             
 
Look at that: it just fits exactly in 16 bytes.  Similar to how every add consists of two XORs, every TC consists of a total of 3 XORs-- plus another 2, to add it.
 
 
 
 
 
===Multiplication: Compare and jump if===
 
 
 
There's more than one way to do multiplication.  We're going to do it like we did back in second grade.
 
 
 
What is 3*3?  It's just 3, plus 3, plus 3.  If we can find a way to keep track of how many times we've added two values, we can multiply.
 
 
 
So far, we've just been going sequentially through our instructions.  But we need to do something different now.  We're going to add a number of times-- we don't even know how many times-- so we need to jump back to our add.
 
 
 
I mentioned earlier that we were going to need a space to keep track of where we are in our program-- so that we can figure out which instruction to execute next.  Jump is extraordinarily simple to implement, so simple that I'm not going to make a diagram for it.  When we jump, all that we do is replace the values in instruction counter-- that is, our memory address-- with the argument we send with the jump instruction.
 
 
 
There's one problem-- eventually, we're going to want to stop adding.  We only want to do it a certain number of times.  So for one thing, we only want our jump to occur if a register is at a certain value.  For another, we need a way to keep track of how many times we've added, and to make sure it's the right number.
 
 
 
We've already designed a compare function.  Currently, that compare function returns greater than, less than, or equal to, but we didn't specify exactly what that meant.  So let's say that if a is greater than b, we write 00000001 into b, and if a is equal to b, we write 00000000 into b, and if a is less than b, we write 11111111 into b.  This is actually how many computers handle this exact situation, by the way.
 
 
 
Now, we need to pick a time to jump.  Let's say that we'll jump if and only if register b is 00000000.  In other words, we jump if not b.  Now we can make our multiplication program:
 
 
 
00001 xxxxxxxxx Operand 1 (factor 1)
 
00010 xxxxxxxxx Operand 2 (factor 2)
 
00011 000000000 Initialized counter
 
00100 000000001 Constant (1)
 
00101 000000000 Initialized output
 
00111 000000000 Constant (0)
 
01000 001000010 Load operand 2 into b
 
01001 000100011 Load counter into a
 
01010 100000000 Compare a and b                          If counter = operand2
 
01011 100110110 Jump to 10111 if not b                  Jump to the end
 
01100 001000100 Load constant(1) into b
 
01101 010100000 XOR
 
01110 010100000 XOR                                      Increment counter
 
01111 001100011 Write a to counter
 
10000 000100101 Load output into a
 
10001 001000001 Load operand 1 into b                   
 
10010 010100000 XOR
 
10011 010100000 XOR
 
10100 001100101 Write a to output                        Output becomes equal to output+operand1
 
10101 010000111 Load constant(0) to b
 
10110 100101000 Jump to 01000 if not b                  Jump to the beginning
 
10111 (program completion)
 
 
 
You can divide the exact same way.  Sequentially subtract your divisor from your dividend until your dividend is smaller than the divisor; the number of times it takes is the quotient, and the remaining dividend is the divisor.  If you don't want a remainder, multiply the remainder by some aribtrarily chosen value (like 2, or 10) and do it again.
 
  
I want you to realize something really cool you can do with a jump: you can write a new address into it with bitshifts and XORs, or you can just plain old increment it (unless it points to 1111-- then incrementing it would change the instruction from jump to something else)A jump doesn't have to be to anyplace in particular.  Your program can change where you jump to.  More black magic, of course.
+
By changing a number to its two's complement value, we can just add it instead of subtracting it.  That's next, as well as:
  
Maybe you noticed that I had to go to 5 addressing bits to make this one work.  Couldn't just start over at 0000, because I needed specific jump addresses.
+
Operation 1001: Compare
 +
Operation 1010: Jump if
 +
Operation 1011: Long jump if
  
Continued at [[User:Vasiln/Goblin Logic 3]]
+
That leaves us with five operations codes to spare: 0000, 1100, 1101, 1110, and 1111.

Please note that all contributions to Dwarf Fortress Wiki are considered to be released under the GFDL & MIT (see Dwarf Fortress Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following CAPTCHA:

Cancel Editing help (opens in new window)