/* * Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com) * */ EXECUTABLE INSTRUCTION OPCODES Instruction opcodes all start with a % character and have 0 or more operands. In no case are there more than 3 operands. This chapter describes the specific behavior of each opcode, in enough detail (I hope) that its complete effect can be predicted. General Principles of Arithmetic (current plan): The binary arithmetic instruction in general takes three parameters, the left operand, the right operand, and the base. The left operand is replaced with the result, which is the same width as the left and right operands. General Principles of Arithmetic (new plan): For strings, all arithmetic is stack based. That is, there is an abstract stack of strings from which operations pull their operands and push their results. This is somewhat like FORTH (or an HP calculator RPN notation) and spares the need to keep register addresses in operands. I may find this leads to a more compact form of instruction code, and may lead to more efficient operators overall, and in particular I may find improved efficiency overall; so after the experience of implementing it for strings, I'll want to change other types around to using this method as well. Keep this in mind whenever considering adding new instructions to vvp. FLAGS There are up to 16 bits in each thread that are available for flags. These are used as destinations for operations that return boolean values, for example comparisons. They are also used as inputs for test and branch opcodes. * %abs/wr , This instruction calculates the absolute value of a real value. It uses the fabs() function in the run-time to do the work. * %add , , (XXXX Old version) This instruction adds the right vector into the left vector, the vectors having the width . If any of the bits of either vector are x or z, the result is x. Otherwise, the result is the arithmetic sum. See also the %sub instruction. * %add This opcode pops and adds two vec4 values from the vec4 stack, adds them, and pushes the result back to the stack. The input values must have the same size, and the pushed result will have the same width. See also the %sub instruction. * %add/wr , This is the real valued version of the %add instruction. The arguments are popped from the stack, right operand then left, and the result pushed in place See also the %sub/wr instruction. * %addi , , This instruction adds the immediate value (no x or z bits) into the left vector. The imm value is limited to 16 significant bits, but it is zero extended to match any width. * %alloc This instruction allocates the storage for a new instance of an automatically allocated scope. * %and Perform the bitwise AND of the two vectors popped from the vec4 stack, and push the result. Each bit is calculated independent of other bits. AND means the following: 0 and ? --> 0 ? and 0 --> 0 1 and 1 --> 1 otherwise x The input vectors must be the same width, and the output vector will be the width of the input. * %and/r Pop the top value from the vec4 stack, perform a reduction &, then return the single-bit result. * %assign/ar , * %assign/ar/d , * %assign/ar/e The %assign/ar instruction assigns a real value to a word in the labeled real array. The is the delay in simulation time to the assignment (0 for non-blocking assignment) and the value is popped from the real value stack. The memory word address is read from index register 3. The address is in canonical form. The %assign/ar/d variation reads the delay from an integer register that is given by the value. This should not be 3 or the index, of course, since these registers contain the word address and the value. The %assign/ar/e variation uses the information in the thread event control registers to determine when to perform the assign. %evctl is used to set the event control information. * %assign/av , , (XXXX Old definition) * %assign/av/d , , (XXXX Old definition) * %assign/av/e , (XXXX Old definition) The %assign/av instruction assigns a vector value to a word in the labeled array. The is the delay in simulation time to the assignment (0 for non-blocking assignment) and the is the base of the vector to write. The width of the vector is retrieved from index register 0. The base of a part select is retrieved from index register 1. The address of the word in the memory is from index register 3. The address is canonical form. The %assign/av/d variation reads the delay from an integer register that is given by the value. This should not be 0, 1 or 3, of course, since these registers contain the vector width, base part select and word address. The %assign/av/e variation uses the information in the thread event control registers to determine when to perform the assign. %evctl is used to set the event control information. * %assign/v0 , , (XXXX Old description) * %assign/v0/d , , (XXXX Old description * %assign/v0/e , (XXXX Old description) The %assign/v0 instruction is a vector version of non-blocking assignment. The is the number of clock ticks in the future where the assignment should be schedule, and the is the base of the vector to be assigned to the destination. The vector width is in index register 0. The %assign/v0/d variation gets the delay instead from an integer register that is given by the value. This should not be 0, of course, because integer 0 is taken with the vector width. The %assign/v0/e variation uses the information in the thread event control registers to determine when to perform the assign. %evctl is used to set the event control information. The references a .var object that can receive non-blocking assignments. For blocking assignments, see %set/v. * %assign/v0/x1 , , * %assign/v0/x1/d , , * %assign/v0/x1/e , This is similar to the %assign/v0 instruction, but adds the index-1 index register with the canonical index of the destination where the vector is to be written. This allows for part writes into the vector. * %assign/vec4 , * %assign/vec4/d , * %assign/vec4/e The %assign/vec4 instruction if a vec4 version of non-blocking assignment, The is the number lf clock ticks in the future where the assignment should schedule, and the value to assign is pulled from the vec4 stack. The %assign/vec4/d instruction is the same, but gets its delay value from the index register instead. * %assign/vec4/a/d , , * %assign/vec4/a/e , This instruction implements delayed assignment to an array word. The value is popped from the vec4 stack; the width is taken from the popped value. The index register contains the canonical offset into the memory word for a part select, and the index register contains the delay for the assignment. Index register 3 contains the word address. The and index registers can be 0, which means a zero value instead of the contents of index register 0. * %assign/vec4/off/d , , This is for writing parts to the target variable. The is the variable to write, as usual. The selects an index register that holds the offset into the target variable, and the selects the index register that contains the delay. The offset is in canonical bits. The width that is written is taken from the width of the value on the stack. * %assign/wr , * %assign/wr/d , * %assign/wr/e This instruction provides a non-blocking assign of the real value given in to the real object addressed by the label after the given . The real value is popped from the stack. The %assign/wr/d variation gets the delay from integer register . The %assign/wr/e variation uses the information in the thread event control registers to determine when to perform the assign. %evctl is used to set the event control information. * %assign/x0 , , (OBSOLETE -- See %assign/v0x) This does a non-blocking assignment to a functor, similar to the %assign instruction. The identifies the base functor of the affected variable, and the gives the delay when the assignment takes place. The delay may be 0. The actual functor used is calculated by using as a base, and indexing with the index[0] index register. This supports indexed assignment. The is the address of the thread register that contains the bit value to assign. * %blend This instruction blends the bits of two vectors into a result in a manner line the expressions ('bx ? : ). The two source vectors are popped from the vec4 stack (and must have the same width) and the result poshed in their place. The truth table for each bit is: 1 1 --> 1 0 0 --> 0 z z --> z x x --> x .... --> x In other words, if the bits are identical, then take that value. Otherwise, the value is x. * %blend/wr This instruction blends real values for the ternary operator. If the values match return that otherwise return 0.0. Two values are popped from the stack, one is pushed back. * %breakpoint This instruction unconditionally breaks the simulator into the interactive debugger. The idea is to stop the simulator here and give the user a chance to display the state of the simulation using debugger commands. This may not work on all platforms. If run-time debugging is compiled out, then this function is a no-op. * %cassign/vec4 * %cassign/vec4/off , Perform a continuous assign of a constant value to the target variable. This is similar to %set, but it uses the cassign port (port-1) of the signal functor instead of the normal assign, so the signal responds differently. See "VARIABLE STATEMENTS" in the README.txt file. * %cassign/wr Perform a continuous assign of a constant real value to the target variable. See %cassign/v above. The value is popped from the real value stack. * %cast2 , , Convert the source vector, of type logic, to a bool vector by changing all the X and Z bits to 0. The source and destinations may overlap. * %cmp/u , , (XXXX Old meaning) * %cmp/s , , (XXXX Old meaning) These instructions perform a generic comparison of two vectors of equal size. The and numbers address the least-significant bit of each vector, and is the width. If either operand is 0, 1, 2 or 3 then it is taken to be a constant replicated to the selected width. The results of the comparison go into bits 4, 5, 6 and 7: 4: eq (equal) 5: lt (less than) 6: eeq (case equal) The eeq bit is set to 1 if all the bits in the vectors are exactly the same, or 0 otherwise. The eq bit is true if the values are logically the same. That is, x and z are considered equal. In other words the eq bit is the same as ``=='' and the eeq bit ``===''. The lt bit is 1 if the left vector is less than the right vector, or 0 if greater than or equal to the right vector. It is the equivalent of the Verilog < operator. Combinations of these three bits can be used to implement all the Verilog comparison operators. The %cmp/u and %cmp/s differ only in the handling of the lt bit. The %cmp/u does an unsigned compare, whereas the %cmp/s does a signed compare. In either case, if either operand contains x or z, then lt bit gets the x value. * %cmp/s * %cmp/u These instructions perform a generic comparison of two vectors of equal size. Two values are pulled from the top of the stack, and not replaced. The results are written into flag bits 4,5,6. The expressions (a, , * %cmpi/u , , These instructions are similar to the %cmp instructions above, except that the right hand operand is an immediate value. This is a positive number that the vector is compared with. * %cmp/wr Compare real values for equality and less-then. This opcode pops to values from the real-value stack and writes the comparison result to bits 4/5. The expressions (a < b) and (a==b) are calculated, with (b) popped from the stack first, then (a). * %cmp/ws , * %cmp/wu , [compare signed/unsigned integer words.] * %cmp/z * %cmp/x These instructions are for implementing the casez and casex comparisons. These work similar to the %cmp/u instructions, except only an eq bit is calculated. These comparisons both treat z values in the left or right operand as don't care positions. The %cmp/x instruction will also treat x values in either operand as don't care. Only bit 4 is set by these instructions. * %cmp/str This instruction pops the top two strings from the string stack and compares them. The results of the comparison go into bits 4 and 5: 4: eq (equal) 5: lt (less than) For the purposes of calculating the lt bit, the top string is the right operand and the string underneath is the left operand. This instruction removes two strings from the stack. * %concat/str * %concati/str Pop the top string, and concatenate it to the new top string. Or think of it as passing the tail, then the head, concatenating them, and pushing the result. The stack starts with two strings in the stack, and ends with one string in the stack. * %concat/vec4 Pop two vec4 vectors, concatenate them, and push the combined result. The top of the vec4 stack is the LSB of the result, and the next in this stack is the MSB bits of the result. * %cvt/sr * %cvt/rs Copy a word from r to l, converting it from real to signed integer (sr) or signed integer to real (rs) in the process. The source and destination may be the same word address, leading to a convert in place. Precision may be lost in the conversion. The %cvt/sr gets the real value from the top of the real value stack (and pops the value) and writes it to the indexed register. * %cvt/ur * %cvt/ru Copy a word from r to l, converting it from real to unsigned integer (ur) or signed integer to real (ru) in the process. The source and destination may be the same word address, leading to a convert in place. Precision may be lost in the conversion. * %cvt/rv , * %cvt/rv/s , The %cvt/rv instruction converts a thread vector starting at and with the width to a real word. Push the result onto the real value stack. Precision may be lost in the conversion. The %cvt/rv/s instruction is the same as %cvt/rv, but treats the thread vector as a signed value. * %cvt/vr The %cvt/vr opcode converts a real word from the stack to a vec4 that is wide. Non-integer precision is lost in the conversion, and the real value is popped from the stack. The result is pushed to the vec4 stack. * %deassign , , Deactivate and disconnect a procedural continuous assignment to a variable. The identifies the affected variable. The and are used to determine what part of the signal will be deactivated. For a full deactivation the is 0 and is the entire signal width. * %deassign/wr The same as %deassign above except this is used for real variables. * %debug/thr These opcodes are aids for debugging the vvp engine. The vvp code generator should not generate these, and they should not alter code flow, data contents, etc. * %delay , This opcode pauses the thread, and causes it to be rescheduled for a time in the future. The amount is the number of the ticks in the future to reschedule, and is >= 0. If the %delay is zero, then the thread yields the processor for another thread, but will be resumed in the current time step. The delay amount is given as 2 32bit numbers, so that 64bit times may be represented. * %delayx This is similar to the %delay opcode, except that the parameter selects an index register, which contains the actual delay. This supports run-time calculated delays. * %delete/obj Arrange for the dynamic object at the target label to be deleted. This has no effect on the object or string stack. Note that this is the same as: %null ; %store/obj but that idiom is expected to be common enough that it warrants an optimized shorthand. * %disable This instruction terminates threads that are part of a specific scope. The label identifies the scope in question, and the threads are the threads that are currently within that scope. * %disable/fork This instruction terminates all the detached children for the current thread. There should not be any non-detached children. * %div , , * %div/s , , This instruction arithmetically divides the vector by the vector, and leaves the result in the vector. IF any of the bits in either vector are x or z, the entire result is x. The %div/s instruction is the same as %div, but does signed division. * %div/wr This opcode divides the left operand by the right operand. If the right operand is 0, then the result is NaN. * dup/real * dup/vec4 These opcodes duplicate the value on the top of the stack for the corresponding type. * %evctl * %evctl/c * %evctl/s * %evctl/i These instructions are used to put event and repetition information into the thread event control registers. These values are then used by the %assign/e instructions to do not blocking event control. The is the event to trigger on and the is an index register to read the repetition count from (signed or unsigned). %evctl/i sets the repetition to an immediate unsigned value. %evctl/c clears the event control information. This is needed if a %assign/e may be skipped since the %assign/e statements clear the event control information and the other %evctl statements assert that this information has been cleared. You can get an assert if this information is not managed correctly. * %event This instruction is used to send a pulse to an event object. The is an event variable. This instruction simply writes an arbitrary value to the event to trigger the event. * %file_line This command emits the provided file and line information along with the description when it is executed. The output is sent to stderr and the format of the output is: :: is the unsigned numeric file index. is the unsigned line number. is a string, if string is 0 then the following default message is used: "Procedural tracing.". * %flag_set/imm , This instruction sets an immediate value into a flag bit. This is a single bit, and the value is 0==0, 1==1, 2==z, 3==x. * %flag_get/vec4 * %flag_set/vec4 These instructions provide a means for accessing flag bits. The %flag_get/vec4 loads the numbered flag as a vec4 on top of the vec4 stack, and the %flag_set/vec4 pops the top of the vec4 stack and writes the LSB to the selected flag. * %force/v