Simple 4-bit/1 Hz virtual computer for learning purposes
github.com
github.com
RAM
ADDR ________
---- |----***-|
---* |---*****|
--*- |--*-*--*|
--** |---****-|
-*-- |-*------|
-*-* |--------|
-**- |--------|
-*** |--------|
*--- |--------|
*--* |-------*|
*-*- |--------|
*-** |--------|
**-- |--------|
**-* |--------|
***- |--------| RAM
ADDR ________
---- |----***-|
---* |---*****|
--*- |--*-**-*|
--** |---****-|
-*-- |-*-*-**-|
-*-* |-*------|
-**- |----**--|
-*** |---****-|
*--- |--------|
*--* |--------|
*-*- |--------|
*-** |--------|
**-- |--------|
**-* |-------*|
***- |--------|
This should get the counter back to 0 after it gets to 255 :) ________
|----***-|
|-*-*-**-|
|---*****|
|--*-*--*|
|---****-|
|-*------|
|----**--|
|---****-|
|-*------|
|-------*|
As you can see, it's pretty much the same, except in mine, the conditional is earlier, and I moved the initial 1 further up... Which required an additional jump?? ...I'd dig deeper but I'm eager to review this other comment, too! RAM AD PC
ADDR ________ _ _
---- |----***-|-|*| ; read in SCRATCH (starts at 0)
---* |---*****|-|-| ; write it to OUTPUT
--*- |--*-**-*|-|-| ; add ONE
--** |---****-|-|-| ; write to SCRATCH
-*-- |-*-*-**-|-|-| ; IF MAX, GOTO LBL_RESET
-*-* |-*------|-|-| ; ELSE, start over
-**- |----**--|-|-| ; LBL_RESET: read in ZERO
-*** |---****-|-|-| ; write the ZERO to SCRATCH
*--- |--------|-|-| ; fall off the world (I think this is where is missing jump is)
*--* |--------|-|-|
*-*- |--------|-|-|
*-** |--------|-|-|
**-- |--------|-|-| ; ZERO (r/o literal)
**-* |-------*|-|-| ; ONE (r/o literal)
***- |--------|-|-| ; SCRATCH (r/w)
**** | OUTPUT |-|-|
If I change his "fall off the world" to a "start over" instruction (-*------) then it works fine RAM AD PC
ADDR ________ _ _
---- |---*****|-|*| ; OUTPUT the register
---* |-*-*-*--|-|-| ; IF MAX, goto LBL_RESET
--*- |--*--**-|-|-| ; else add ONE to the register...
--** |-*------|-|-| ; ...and start over.
-*-- |-----***|-|-| ; LBL RESET: read in ZERO to the register...
-*-* |-*------|-|-| ; ...and start over.
-**- |-------*|-|-| ; ONE (r/o data)
-*** |--------|-|-| ; ZERO (r/o data)If you could control the initial register value to set it to , this would be a quine:
RAM AD PC
ADDR ________ _ _
---- |---*****|-|*|
---* |---*****|-|-|
--*- |---*****|-|-|
--** |---*****|-|-|
-*-- |---*****|-|-|
-*-* |---*****|-|-|
-**- |---*****|-|-|
-*** |---*****|-|-|
*--- |---*****|-|-|
*--* |---*****|-|-|
*-*- |---*****|-|-|
*-** |---*****|-|-|
**-- |---*****|-|-|
**-* |---*****|-|-|
***- |---*****|-|-|
**** | OUTPUT |-|-|
############
But since you can't, that instead prints out all zeroes.I don't have any other ideas :)
RAM AD PC
ADDR ________ _ _
---- |-----*-*|-|*| ; read FOO
---* |---*----|-|-| ; write FOO to 0 (now points at BAR)
--*- |---*****|-|-| ; print
--** |-*------|-|-| ; back to the top!
-*-- |-----*-*|-|-| ; BAR
-*-* |-----*--|-|-| ; FOO
-**- |--------|-|-|
-*** |--------|-|-|
*--- |--*---*-|-|-| ; a grand tradition in ROMs
*--* |--------|-|-| ; though this isn't a ROM
*-*- |----*---|-|-| ; anymore, is it? :)
*-** |--------|-|-|
**-- |--*---*-|-|-|
**-* |---***--|-|-|
***- |--------|-|-| RAM AD PC
ADDR ________ _ _
---- |*--*----|-|*| ; high bit set? Instruction = READ
---* |-***----|-|-|
--*- |--*-**-*|-|-|
--** |---*----|-|-|
-*-- |-*------|-|-|
-*-* |--------|-|-|
-**- |--------|-|-|
-*** |--------|-|-|
*--- |*-*-----|-|-|
*--* |--------|-|-|
*-*- |--------|-|-|
*-** |--------|-|-|
**-- |--------|-|-|
**-* |*-------|-|-|
***- |--------|-|-|
I had a basic idea of what I wanted to do here: to write instructions and subsequently execute them: self modifying code.That's as far as I've got, and I got there by twiddling bits, not by engineering...
That would be enough to classify it as an 8-bit machine, despite the fact that instructions are only 4 bits wide. A real 4-bit CPU, like the 4004, has 4-bit registers.
This gets even muddier with the Pentium MMX, which has a set of 64-bit MMX registers. Of course there's also 80-bit-wide registers in the FPU of everything back to the 8087...
Bitness is a surprisingly subtle thing to define, but I think an 8-bit-wide GPR is enough for this one to be called 8-bit.
Take the 80386SX for another somewhat convoluted example: 32-bit general purpose registers so considered a 32-bit CPU, but some of those registers are effectively composed of chunks that can be used independently to work with 8 or 16 bits at a time, it has a 24-bit address bus, and a 16-bit data bus (which uses multiple requests when asked to bring or push a 32-bit value - this was the primary difference between the 386 (later dubbed 386DX) and 386SX models).
Didn't realize that, and you're right. Other examples of CPU's that I'm aware of with a different "bitness"/databus width are the 68008 and 8808, but in both cases the data bus is smaller than the "bitness".
RAM AD PC
ADDR ________ _ _
---- |---****-|-|*|
---* |----**-*|-|-|
--*- |---***--|-|-|
--** |--*-***-|-|-|
-*-- |---***-*|-|-|
-*-* |----**--|-|-|
-**- |---*****|-|-|
-*** |-*------|-|-|
*--- |--------|-|-|
*--* |--------|-|-|
*-*- |--------|-|-|
*-** |--------|-|-|
**-- |--------|-|-|
**-* |-------*|-|-|
***- |--------|-|-|
**** | OUTPUT |-|-|
But due to the saturating arithmetic, it gets to 255 and then just prints 255 over and over. I tried to write one that would reset itself when that happens, but I can't seem to do it in 15 bytes (I have a 14 instruction+3 variable version but of course 17 bytes won't fit in RAM)Edit: I can save one of the variables with a set-immediate instruction :) https://github.com/gto76/comp-cpp/pull/7
If I understand the README correctly, it looks like the left 4 bits are the instruction, and the right 4 bits are the address. So the line ---1--1- would mean "READ the value from address 0010 into the register". Is the correct interpretation? If so, how do I put a value onto the register in the first place? How I do I set the value at an address?
Let's say I wanted to add 0001 + 0001 and show the output as 0010 on the printer. How would I do that?
The file in question: https://github.com/gto76/comp-cpp/blob/e800d121e40f8acca6b9d....
And the -1 seems to be explained by how the author wants to use it, it's "last valid address", i.e. not the size at all. Something I'd complain about if this were open for review, for sure. :)
I can't be the only one who thought this, right?!
"The Terminator is an accounting programme run amok"
- https://github.com/trillek-team/trillek-computer/blob/master...
- https://github.com/trillek-team/trillek-vcomputer-module
- https://github.com/trillek-team/computer-toolkit
The official implementation it's a standlone library, and has been tested running at same time around 1000 VM's (on a single thread). So if some one implements a server and a web-client with it, could be very nice for this kind of stuff.
And there is a macro assembler (VASM), linker (VLINK) and SmallerC compiler for it.