Sieve of Eratosthenes little man computer - sieve-of-eratosthenes

Could someone help me understand, why this work only when input<69 ?
I'm working with simple assembly code for Little Man Computer
INP
STA INPUT
LDA C
OUT
ADD ONE
OUT
LOOP LDA A \\ first loop
ADD ONE
STA A
SUB INPUT
BRP END
LDA A
ADD LDINS
STA READINS
READINS DAT
BRZ PRIME
BRA LOOP
PRIME LDA A
OUT
STA B
WRITELOOP LDA B \\ second loop
SUB INPUT
BRP LOOP
LDA B \\ at this moment program breakdown when input is more than 69
ADD STINS
STA WRINS
LDA A
WRINS DAT
LDA B
ADD A
STA B
BRA WRITELOOP
END HLT
INPUT DAT 0
LDINS DAT 531 \\ this is working, but i think i might do a better code
STINS DAT 331
A DAT 1
ONE DAT 1
B DAT
C DAT 2
I'm use of http://peterhigginson.co.uk/lmc/ to try to work this program

The program breaks down above input value 69, because of the limited memory that is available to an LMC. The highest possible address (mailbox) is 99.
This code uses memory space for the sieve, which needs to be as large as the input you give to it. The memory for the sieve starts at mailbox 31, which is defined at label LDINS and STINS in your code: 531 means LDA 31, where 31 is a mailbox address. Similarly 331 means STA 31. This defines the maximum size of the sieve: 31 to 99 gives a total of 69 mailboxes that can serve for the sieve.
The instruction STA WRINS will dynamically change the code at label WRINS so that it writes a value in the sieve array. The dynamic opcode written is 300 + 31 + [some dynamic offset]. The 300 stands for STA, and 31 is where the sieve array starts. Now when the offset is 69 or more, this instruction becomes 400 or more, which no longer represents a STA instruction, but an undefined opcode.
You can run your code in the snippet below, and when you give it 70 as input, you will see it stalls at that instruction saying that the opcode is invalid:
#input: 70
INP
STA INPUT
LDA C
OUT
ADD ONE
OUT
LOOP LDA A \\ first loop
ADD ONE
STA A
SUB INPUT
BRP END
LDA A
ADD LDINS
STA READINS
READINS DAT
BRZ PRIME
BRA LOOP
PRIME LDA A
OUT
STA B
WRITELOOP LDA B \\ second loop
SUB INPUT
BRP LOOP
LDA B \\ at this moment program breakdown when input is more than 69
ADD STINS
STA WRINS
LDA A
WRINS DAT
LDA B
ADD A
STA B
BRA WRITELOOP
END HLT
INPUT DAT 0
LDINS DAT 531 \\ this is working, but i think i might do a better code
STINS DAT 331
A DAT 1
ONE DAT 1
B DAT
C DAT 2
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc#v0.76/lmc.js"></script>
So concluding, this behaviour is not really a bug in the program, but more a memory limitation of the LMC. An LMC implementation of the Sieve of Eratosthenes will always have a limitation somewhere around that size, depending how concise you can make the code -- leaving room for the array.
Remarks about the code
The above answers your question, but there are some comments to make about your code.
It seems you modified an existing program, adding some preliminary instructions to output 2 and 3 quickly, but you didn't adapt the starting address of the sieve memory in accordance. In your current program the address 31 points to the line (mailbox) with BRA WRITELOOP, which cannot be your purpose. The first time the dynamic code at READINS is executed, that location has instruction LDA INPUT as INPUT, corresponding to address 33.
This is also the reason why the program does not output 5 as a prime. The program should really point to free memory for its sieve, beyond the data you already have in use. To save space you could let the sieve address start at label ONE, since the first two entries of the sieve are never accessed.
I think it is also better to use labels and mnemonics instead of hardcoded opcodes and addresses, so avoiding things like 331 and 531, which are quite cryptic, and (as demonstrated) are error prone when the program is modified.
Also, you should explicitly list the DAT entries that your program will use.
Here is a corrected version, which obviously still has a limit on the input: 67 is the maximum value you can input without breaking the code.
#input: 67
INP
STA INPUT
LOOP LDA A \\ first loop
ADD ONE
STA A
SUB INPUT
BRP END
LDA A
ADD LDINS
STA READINS
READINS DAT
BRZ PRIME
BRA LOOP
PRIME LDA A
OUT
STA B
WRITELOOP LDA B \\ second loop
SUB INPUT
BRP LOOP
LDA B
ADD STINS
STA WRINS
LDA A
WRINS DAT
LDA B
ADD A
STA B
BRA WRITELOOP
END HLT
INPUT DAT
LDINS LDA ONE
STINS STA ONE
A DAT 1
ONE DAT 1 // also the start of the sieve
B DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc#v0.76/lmc.js"></script>

Related

How to calculate Hamming code of (31,26)?

I need to construct the (31,26) hamming code of 0x444.
After reading Wikipedia and the algorithm shown in GeeksForGeeks I still can't understand how this works as my construction ended up different than the result of a calculator I found on the internet.
My result is: 0100 0100 0010 0010 or 0x4422
is it correct?
As I understand:
P1 = Bitwise XOR(C1,C3,C5,C7,C9,C11,C13.C15,C17..) = 0
P2 = Bitwise XOR(C2,C3,C6,C7,C10,C11,C14,C15..) = 1
P3 = Bitwise XOR(C4,C5,C6,C7,C12,C13,C14,C15..) = 0
P4 = Bitwise XOR(C8,C9,C10,C11,C12,C13,C14,C15..) = 0
P5 = Bitwise XOR(C16,C17..) = 0
Another thing I can't understand.. if (31,26) hamming code is supposed to output a 31 bit result with 5 parity bits and 26 data bits.. why (7,4) hamming code transforms each 4 bits to 7 bits representation and not just 1 representation of 7 bits with 3 parity bits?
Thanks.
Yes, assuming you are numbering the bits from 1 at the right-hand end, then 0x000444 is encoded as 0x00004422 for a (31,26) Hamming Code -- for an even parity code-word.
Where C1, C2, etc are bit 1, 2, etc of the code-word, and P1, P2, etc are parity bits 1, 2, etc. I think is clearer to say that:
P1 = C1 = Bitwise_XOR(C3, C5, C7, C9, ...)
so that:
Bitwise_XOR(C1, C3, C5, C7, C9, ...) == 0
and so on. This is even parity.
You do not say which "calculator" you tried, but it could be that the discrepancy you see is to do with what end you number from. I note that Wikipedia gives:
If a byte of data to be encoded is 10011010, then the data word (using _ to represent the parity bits) would be __1_001_1010, and the code word is 011100101010.
which is clearly counting bits from the left-hand end.
I regret I do not understand your second question. I can say that a (31,26) Hamming Code does indeed take 26 bits of data and adds 5 parity bits to produce a 31 bits code-word. And that a (7,4) Hamming Code does likewise for 4 bits of data, 3 parity bits and a 7 bit code-word.

PLC Ladder logic - How to simulate measurments of water flow in PLC?

I can't figure out how to solve this task using PLC ladder language. PLC programme must compute actual flow of water. The gate is moving and the time of gate is set to 5 minutes. In this gate the impulses are counted (with wage for example - wage of 1 m^3). The overall time (the space where the gate can move) is set to 1 hour.
Gate time: for example 5 minutes
Overall time: 1 hour
Impulse is triggered by me.
Example if we trigger the I1 input - 3 times (one input have wage 1 m^3) in a gate of 5 minutes (5 minutes is 1/12 hour) so 3 * 1m^3 divided by (1/12)h = 36 m^3 / h It gave us actual water flow. I can only use TON timer and I've got 2 binary inputs.
Do you have any idea how to start this?
Exercise
It's a logger I tried to base on, but now I don't know what to do next.
#include "MT-101.h"
IF FS1_fs MOVE 0, REG2
IF FS1_fs MOVE RTC_Sec, REG2
NE RTC_Sec, REG2, Q1
IF NOT Q1 EXT
MOVE RTC_Sec, REG2
IF NOT I1 EXT
TCPY XREG1, 511, XREG2
MOVE AN1, XREG1

how can i determine successive (logic'1') bits in a std_logic_vector

i am pretty a new vhdl user and i am trying to solve a problem,which is difficult for me nowadays . I have two std_logic_vectors.First one has 5 bits,which must have (11111).Second one has 2040 bits,which is arbitral and i must divide up 2040 bits to 24 outputs that means each output must have 85 bits .First i must determine by using a small vector(5bits) the place of successive 5 bits(11111) in a std_logic_vector,which has 2040 bits.After determing if there are (11111) in a 2040bits vector ,the output should be '1' which is responsible 85 bits where there is (11111) .
to summarize
for example i have 24 outputs each control 85 bits of std_logic-vector(2040bits)
if there is a 11111 in first 85 bits then output1 should be '1'
if there is a 11111 in 86 to 170 bits then output2 should be '1'
if there is a 11111 in 172 to 255 bits then output3 should be '1' so on...
(11111) is the minimum value .it can be bigger to make an output logic '1' Does someone have any idea about it??... and ((if 2040bits are massive then i can reduce the number of bits))
Thanks
I suspect you mean to search for the first vector in the second, however if you know that they will all be '1's, then the and_reduce macro works nicely. Otherwise replace that with a comparison.
The general principal is to break it into two loops, the outside is for each output result, and the inside is for each possible 5 bit group. The process can be done in serial or in parallel like below.
the way you've described the problem if 81 to 86 = "11111" there will be no pattern match. if that should return a 1, then the array bounds will need to be altered slightly.
type slvArray is array (natural range <>) of standard_logic_vector;
subtype outputRange is natural range 0 to 23;
subtype partitionRange is natural range 0 to 84;
proc:process(clock)
variable andResult : slvArray(outputRange)(partitionRange);
begin
if rising_edge(clock) then
for olc in outputRange loop
for ilc in partitonRange'low to partitionRange'high-4 loop
andResult(olc)(ilc) <= and_reduce(slv2(olc*partitionRange'length + ilc to olc*partitionRange'length+ ilc + 4);
end loop;
output(olc) <= or_reduce(andResult);
end loop;
end if;
end process;

Why does a 4 bit adder/subtractor implement its overflow detection by looking at BOTH of the last two carry-outs?

This is the diagram we were given for class:
Why wouldn't you just use C4 in this image? If C4 is 1, then the last addition resulted in an overflow, which is what we're wondering. Why do we need to look at C3?
Overflow flag indicates an overflow condition for a signed operation.
Some points to remember in a signed operation:
MSB is always reserved to indicate sign of the number
Negative numbers are represented in 2's complement
An overflow results in invalid operation
Two's complement overflow rules:
If the sum of two positive numbers yields a negative result, the sum has overflowed.
If the sum of two negative numbers yields a positive result, the sum has overflowed.
Otherwise, the sum has not overflowed.
For Example:
**Ex1:**
0111 (carry)
0101 ( 5)
+ 0011 ( 3)
==================
1000 ( 8) ;invalid (V=1) (C3=1) (C4=0)
**Ex2:**
1011 (carry)
1001 (-7)
+ 1011 (−5)
==================
0100 ( 4) ;invalid (V=1) (C3=0) (C4=1)
**Ex3:**
1110 (carry)
0111 ( 7)
+ 1110 (−2)
==================
0101 ( 5) ;valid (V=0) (C3=1) (C4=1)
In a signed operation if the two leftmost carry bits (the ones on the far left of the top row in these examples) are both 1s or both 0s, the result is valid; if the left two carry bits are "1 0" or "0 1", a sign overflow has occurred. Conveniently, an XOR operation on these two bits can quickly determine if an overflow condition exists. (Ref:Two's complement)
Overflow vs Carry: Overflow can be considered as a two's complement form of a Carry. In a signed operation overflow flag is monitored and carry flag is ignored. Similarly in an unsigned operation carry flag is monitored and overflow flag is ignored.
Overflow for signed numbers occurs when the carry-in into the most significant bit is not equal to the carry out.
For example, working with 8 bits, 65 + 64 = 129 actually results in a overflow. This is because this is 1000 0001 in binary which is also -127 in 2's complement. If you work through this example, you can see that it is a result of the carry out not equalling the carry in.
It is possible to have a correct computation even when the carry flag is high.
Consider
1000 1000 = -120
+ 1111 1111 = -1
=(1) 10000111 = -121
There is a carry out of 1, but there has been no overflow.
I would like the give a more general answer to this question for any positive natural number of bits.
Lets call the last Carry output C1, the second to last Carry output C0, the sum sign output S0 and the signbits of A and B respectively A0 and B0.
Then the following holds:
C1 = A0 + B0 + C0
S0 = A0*B0 + A0*C0 + B0*C0
Lets now walk through the posibilities.
If C1 == 1 there are two possibilities:
if C0 == 0: A0 and B0
must both have been 1 (and thus both A en B must be negative). This
means S0 has to be 0 meaning the solution was positive while A en B
were negative => overflow
if C0 == 1: either
A en B have opposite signs, so overflow is not possible. => no overflow
A0 en B0 are both 1 (and thus A en B
must both be negative). This means S0 has to be 1 meaning the solution was negative => no overflow
If C1 == 0 there are two possibilities:
if C0 == 0: either
A0 en B0 are both 0 (and thus A en B
must both be positive). This means S0 has to be 0 meaning the solution was positive => no overflow
A en B have opposite signs => no overflow
if C0 == 1: A0 en B0 must both be 0 (and thus A en B
must both be positive) This
means S0 has to be 1 meaning the solution was negative while A en B
were positive => overflow
Hope that helps someone out there.

Algorithm for sequence calculation

I'm looking for a hint to an algorithm or pseudo code which helps me calculate sequences.
It's kind of permutations, but not exactly as it's not fixed length.
The output sequence should look something like this:
A
B
C
D
AA
BA
CA
DA
AB
BB
CB
DB
AC
BC
CC
DC
AD
BD
CD
DD
AAA
BAA
CAA
DAA
...
Every character above represents actually an integer, which gets incremented from a minimum to a maximum.
I do not know the depth when I start, so just using multiple nested for loops won't work.
It's late here in Germany and I just can't wrap my head around this. Pretty sure that it can be done with for loops and recursion, but I have currently no clue on how to get started.
Any ideas?
EDIT: B-typo corrected.
It looks like you're taking all combinations of four distinct digits of length 1, 2, 3, etc., allowing repeats.
So start with length 1: { A, B, C, D }
To get length 2, prepend A, B, C, D in turn to every member of length 1. (16 elements)
To get length 3, prepend A, B, C, D in turn to every member of length 2. (64 elements)
To get length 4, prepend A, B, C, D in turn to every member of length 3. (256 elements)
And so on.
If you have more or fewer digits, the same method will work. It gets a little trickier if you allow, say, A to equal B, but that doesn't look like what you're doing now.
Based on the comments from the OP, here's a way to do the sequence without storing the list.
Use an odometer analogy. This only requires keeping track of indices. Each time the first member of the sequence cycles around, increment the one to the right. If this is the first time that that member of the sequence has cycled around, then add a member to the sequence.
The increments will need to be cascaded. This is the equivalent of going from 99,999 to 100,000 miles (the comma is the thousands marker).
If you have a thousand integers that you need to cycle through, then pretend you're looking at an odometer in base 1000 rather than base 10 as above.
Your sequence looks more like (An-1 X AT) where A is a matrices and AT is its transpose.
A= [A,B,C,D]
AT X An-1 ∀ (n=0)
sequence= A,B,C,D
AT X An-1 ∀ (n=2)
sequence= AA,BA,CA,DA,AB,BB,CB,DB,AC,BC,CC,DC,AD,BD,CD,DD
You can go for any matrix multiplication code like this and implement what you wish.
You have 4 elements, you are simply looping the numbers in a reversed base 4 notation. Say A=0,B=1,C=2,D=3 :
first loop from 0 to 3 on 1 digit
second loop from 00 to 33 on 2 digits
and so on
i reversed i output using A,B,C,D digits
loop on 1 digit
0 0 A
1 1 B
2 2 C
3 3 D
loop on 2 digits
00 00 AA
01 10 BA
02 20 CA
03 30 DA
10 01 AB
11 11 BB
12 21 CB
13 31 DB
20 02 AC
21 12 BC
22 22 CC
...
The algorithm is pretty obvious. You could take a look at algorithm L (lexicographic t-combination generation) in fascicle 3a TAOCP D. Knuth.
How about:
Private Sub DoIt(minVal As Integer, maxVal As Integer, maxDepth As Integer)
If maxVal < minVal OrElse maxDepth <= 0 Then
Debug.WriteLine("no results!")
Return
End If
Debug.WriteLine("results:")
Dim resultList As New List(Of Integer)(maxDepth)
' initialize with the 1st result: this makes processing the remainder easy to write.
resultList.Add(minVal)
Dim depthIndex As Integer = 0
Debug.WriteLine(CStr(minVal))
Do
' find the term to be increased
Dim indexOfTermToIncrease As Integer = 0
While resultList(indexOfTermToIncrease) = maxVal
resultList(indexOfTermToIncrease) = minVal
indexOfTermToIncrease += 1
If indexOfTermToIncrease > depthIndex Then
depthIndex += 1
If depthIndex = maxDepth Then
Return
End If
resultList.Add(minVal - 1)
Exit While
End If
End While
' increase the term that was identified
resultList(indexOfTermToIncrease) += 1
' output
For d As Integer = 0 To depthIndex
Debug.Write(CStr(resultList(d)) + " ")
Next
Debug.WriteLine("")
Loop
End Sub
Would that be adequate? it doesn't take much memory and is relatively fast (apart from the writing to output...).

Resources