Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers DBPro Corner / Help with something unusual

Author
Message
std
20
Years of Service
User Offline
Joined: 6th Jun 2004
Location: Bucharest, Romania
Posted: 6th Jun 2004 16:40
I'm currently trying to find a few new uses for DarkBASIC aside from some games I've done, and I ran into a bit of a problem.
I'm trying to create an emulator for a very simple CPU (details here: http://www.creighton.edu/~davereed/csc107/Chapters/14-Work.html). The only change is that there are two memory segments - one used to store the program, the other one just for output.
Most of the things are quite straightforward, the only thing I have no idea about is how to decode instructions.
Instructions are 16-bit, as following:

add contents of two registers, store result in another register
e.g., R0 = R1 + R2
1010000100 RR RR RR
1010000100 00 01 10
will add contents of R1 (01) and R2 (10), store the result in R0 (00)

subtract contents of two registers, store result in another register
e.g., R0 = R1 - R2
1010001000 RR RR RR
1010001000 00 01 10
will take contents of R1 (01), subtract R2 (10), and store the result in R0 (00)

load contents of memory location into register
e.g., R3 = M[5]
100000010 RR MMMMM
100000010 11 00101
will load contents of memory location 5 (00011) into R3 (11)

store contents of register into memory location
e.g., M[5] = R3
100000100 RR MMMMM
100000100 11 00101
will store contents of memory location 7 (00101) into R3 (11)

move contents of one register into another register
e.g., R1 = R0
100100010000 RR RR
100100010000 01 00
will move contents of R0 (00) into R1 (01)

halt the machine
1111111111111111

I'm storing all these instructions in the progra memory, which is a 32-square vector (1-dimensional array), one instruction per square.
Of course, it would have been very simple if the size of each of these instructions would have been the same...but it's not quite so.
>>>Also, a small request for an advice all those instructions are in binary. How can I represent a binary number in DarkBASIC?

Thank you, and I sincerely hope this hasn't been an "insult" ) it's just that I want to use DarkBASIC for more than just games.

~There are alternatives to fighting~
std
20
Years of Service
User Offline
Joined: 6th Jun 2004
Location: Bucharest, Romania
Posted: 6th Jun 2004 16:47
Using DarkBASIC Classic, sorry for not mentioning it in the first place.

~There are alternatives to fighting~
Ninja Matt
20
Years of Service
User Offline
Joined: 5th Jun 2004
Location: Lincolnshire, UK
Posted: 6th Jun 2004 19:46 Edited at: 6th Jun 2004 19:47
Well, I'm not really an expert, but I can try to help a little!

It might be somewhat memory-munching, but you could try representing the program memory with a two-dimensional array, having the first vector to represent each square in the memory, while the second vector represents each of the bit flags within a square. Then again, you could also try representing the program memory with a series of strings, rather than integers.

Actually, on second thoughts, if you've got the enhancement pack for DB, you should have access to memblocks too. If you can learn how to use them, you'll be able to represent anything! The best way to represent shorter instructions would be to pad them out with 0s or something, to make all instructions the same size, and then keep a record of how long each instruction should actually be in a seperate array.

Hope this helps!
DeepBlue
21
Years of Service
User Offline
Joined: 17th May 2003
Location: A little box in the UK
Posted: 6th Jun 2004 21:04
Ah, knew my days of designing/building motherboards would come in useful one day lol

Suggestions that should help are:

1. To simplify your task to start with I would recommend having 2 arrays (you can merge them later). One to hold the program & one to hold the data. Decide on your maximum Instruction size, lets say we will have 1 Command element and 2 operands for now eg. [LD_r_n][r][n] , so our maximum instruction size is 3. We will therefore store all our instructions starting at intervals of 3 eg. 0,3,6,9 etc

Not using binary to aid understanding out data would look similar to



2. As in a real processor we will use a 'Program Counter' to point at our array (memory), the program counter is going to hold the memory address (array pointer) of the instruction to execute. So in our case it will start at 0 execute the instruction and then increase the program counter by 3 which is the next instruction. NB, If the instruction is a jump instruction (goto) we will not increment the program counter by 3 but set it to the value specified in the jump instruction.

In db psuedo code we are doing something similar to:



3. As more of a side note I would strongly suggest adding an Accumulator which is one of your registers which can be used as both the source for, and destination of calculations ie.

LD_r_n A,4 (load Accumulator with 4)
LD_r_n B,7 (load B register with 7)
ADD_A_r B (add A and B and return result in A)

The above conforms to a more standard way in which processors work and also why use 3 registers when you can use 2 It will also cut down the following code under section 4 dramatically.

4. OK now we have the basics in place all we need to do is evaluate and act on each of the commands our program counter points to. To do this we just need to use the select and case commands.

Our new DB pseudo would look similar to (it will get lenghty as we cant read the variable name ie. the register, and write to it unless we use pointers)



The above would allow the following commands
COMMAND operator1,operator2

LD_r_n r, n `Loads a register with a number
ADD_A_r r `Adds a register to the accumulator
ADD_A_n n `Adds a number to the accumulator
JUMP n `Jump to specified program location


Note it is important we use different commands depending whether we are dealing with registers or numbers, as a numerical value of say 1 in the program array could refer to either.

Hope thats a good starter for 10

Oh and if you want to specify binary numbers in code use % ie A=%1001 =9dec
if you want to change them into a string use bin$ ( )
if you want a dec to bin string converter i posted 1 here within last couple of weeks.

Twynklet
DeepBlue
21
Years of Service
User Offline
Joined: 17th May 2003
Location: A little box in the UK
Posted: 6th Jun 2004 21:24
I posted before I looked at that page

That is one of the worst, most overcrammed examples (of well just about everything to do with CPU architecture I've ever seen). Wierd as its from a Prentice-Hall publication.

I pitty you if this is some kind of coursework you have to follow.

OK been to the atic & found what was a bible to me several years back, I have no idea if it's still in publication or whether its been updated (in some respects it need it)

Its called
Microcomputers and Microprocessors
The 8080,8085, and Z80
Programming, Interfacing, and Troubleshooting
second edition.
Publisher: Prentice-Hall
Author: John Uffenbeck (I am not worthy no utter his name)

Snappy title aint it, and not light reading. But nice because it's all 8 & 16 bit and covers what it says on the tin so to speak.

I'd suggest either getting yourself a machine code compiler for your pc (yes I know its off-topic but im on a roll now), or get a Z80 emulator with compiler as Z80 is very easy to learn. Think you can still get the older processor, its good because there so old and slow you can even knock up a little machine on a plugblock.

Hmm Zilog Z80 im off to dream about shadow registers now..bah those Intel ppl have no idea

Twynklet
SandraD
20
Years of Service
User Offline
Joined: 30th May 2004
Location: Down on the corner, out in the street.
Posted: 7th Jun 2004 04:45
Actually,

If you are emulating a CISC type of processor the basic method is to read the first byte of the command then branch out to the routine that actually processes that code, including the variable length of the data the command requires. As most of today's processors use bit compression for their function, ie; XXYY ZZZZ for each component of the operation (X=memory/register Y=word/byte Z=command, etc.) this generally requires you to code out a CASE statment for that first byte in all combinations then use a global pointer to the memory array to fetch data the subroutine uses to process that command. (Or the PC pointer as Twynlet was saying.)

A better process is to "bit slice" the command word as it makes programming easier (IE, just cut off the XX, YY or ZZZZ parts) but most BASICs (including DB) are not very good at these operations. It can be done though, it just tends to slow down the compiler as the data is manipulated.

Any truly great code should be indisguishable from magic.
Emperor Baal
20
Years of Service
User Offline
Joined: 1st Dec 2003
Location: The Netherlands - Oudenbosch
Posted: 7th Jun 2004 04:59
The worlds first software emulated Hyperthreading cpu
Intel would be jealous

std
20
Years of Service
User Offline
Joined: 6th Jun 2004
Location: Bucharest, Romania
Posted: 7th Jun 2004 20:39
Thank you very much, all of you.
First of all, after kindda bugling with the thing I decided to drop that stupid design ) and make my own .
Due to the fact that this is a *very* simple CPU (I'm willing to end up writing a serious emulator, but I want to start small and go on later...2 weeks 'till holidays for me so I have a summer at disposal), all the instructions would fit in a nibble so it's no big deal.
Actually, since they would fit in a nibble (4 bits), I'd have room for 16 instruction => 15 "normal" instructions and 1 for halt (1111).
So we'd have the command like: [nibble][arg1][arg2][arg3] - which would be quite OK - some instructions may get 3 arguments (e.g. add r1 r2 r3 - r3 = r1+r2...though that's kindda obfuscated).
So we'd also have a nibble for each argument, that lets me have 16 registers as well.
Intstruction which imply memory would have an 8-bit argument which is the address. Which means that I'd get 256 memory locations, say, 16 bit each => (2^8 * 2 ^ 4) / 2*3 = 2^9 = 512 bytes of program memory. Which is okay (p.s. I know Z80 programming so I can keep them small...besides there's no big deal of a program you could do with this CPU).
The only (slight) problem would be the different size of the arguments, but I could easily fix that with the function that decodes the instruction (I'll immediately show you how).

Now, the idea is that I want something quite realistic though (sure, I'm not going for a full-fledged RISC CPU so I can change things a bit ). The program memory would be a multi-dimensional array, say:
program(256,4). It would go like this:
program(i,0) - store the instruction
program(i,1) - store arg1
program(i,2) - store arg2
program(i,3) - store arg3
They will be all strings 'cause I'm not willing to get overcomplicated right now, no big deal about it though, may change this later.
If an argument is a memory location, arg1 (a register) remains the same, and then I just concatenate arg2 and arg3. Of course they would be binary, so after I make that an integer I'd also have to turn into decimal so that I can address that memory location, but that's easy to do as well. So far, it's okay I guess.

I plan to have two memory arrays anyway - one to store the program, one to store the data (e.g. output of the memory), that's how it's done on modern CPUs anyway.

Maybe I'll do a very basic output to LEDs , that's shouldn't be hard to implement, no big deal really.

Hmm....I don't have very much time these days since school is coming to an end and I have a few marks to fix ) but I won't abandon everything, work will progress quite slowly though (I only used DARK Basic for a two or three weeks and done only some small, itty-bitty games, so my knowledge of the language is not complete). Thank you very much again, and I promise to keep you informed on this.

~There are alternatives to fighting~
std
20
Years of Service
User Offline
Joined: 6th Jun 2004
Location: Bucharest, Romania
Posted: 7th Jun 2004 20:54
Hmmm...btw, can you invoke DarkBASIC compiler from a command line?
I got a bit tired of the DarkBASIC IDE, it changes my screen resolution and I hate the fonts&the colors.
Hmmm...mneah, I'll use UltraEdit anyway, just curios, I hate doing copy&paste for a quick compile to check for syntax errors.

~There are alternatives to fighting~
std
20
Years of Service
User Offline
Joined: 6th Jun 2004
Location: Bucharest, Romania
Posted: 7th Jun 2004 22:16
Hmmmm...one error in the spec though.
I will have to change things a bit if I want that much memory, 8 bits won't be enough to address 1 kilobyte of memory.

~There are alternatives to fighting~
DeepBlue
21
Years of Service
User Offline
Joined: 17th May 2003
Location: A little box in the UK
Posted: 8th Jun 2004 09:41
Do what other 8bit processors do with 16-bit address busses..use 2 registers to hold memory address locations.

BTW as you hate the DB editor I take you are using DBC there command line options for db.exe are
-c compile
-x execute
-b make exe
-f build final

Alternatively I suggest you just download a copy of DarkEdit, can't remember url as it's been years since I download it but you will prbably like it.
std
20
Years of Service
User Offline
Joined: 6th Jun 2004
Location: Bucharest, Romania
Posted: 8th Jun 2004 10:57
Nah, actually I realized that there are so few instructions (8 including hlt ) that 1 kilobyte of memory is quite a lot. So I just stripped down the memory.
There are 128 locations x 16 bit in the program memory (which is more than enough), and 128 x 4 bit in the output memory. As I said, this is more than enough, because I want to keep things as simple as possible, not necessarily realistic. Realism will come later.
I will try Dark Edit...though the chances of making me let UltraEdit away are quite low. Thanks anyway.

~There are alternatives to fighting~
std
20
Years of Service
User Offline
Joined: 6th Jun 2004
Location: Bucharest, Romania
Posted: 8th Jun 2004 11:27
So far, we got them like this:

You will see that this is quite unrealistic though, as some of the registers addresses will interfere with memory addresses, but as I said, I want to keep things simple, not necessarily realistic.
Also, this was not yet compiled, so there may be errors, it's written in a two-minute's time.

~There are alternatives to fighting~
std
20
Years of Service
User Offline
Joined: 6th Jun 2004
Location: Bucharest, Romania
Posted: 8th Jun 2004 12:35
Sorry, me stupid:
Code is under "source", not the code snippet.
BTW, how can I edit my posts in this forum?

~There are alternatives to fighting~
SandraD
20
Years of Service
User Offline
Joined: 30th May 2004
Location: Down on the corner, out in the street.
Posted: 9th Jun 2004 07:48
Heh-heh-heh!

Going with a nibble style reminds of the predessor of the processor you say that you know, specifically the Intel 4004. (Later 8008, 4040 then 8080, etc.) I wrote an emulator for that puppy many years ago in Rare Basic, so I know DB can handle it. And by the way, that processor had 97 commands, including the register shifts and rotates classed under one higher nibble command.

I wonder however, why are you working with the binary values as strings when it's so much easier to just make them into integers for testing and operation, then convert to binary represented strings using a suitable function for display? DB has all the commands needed for this, and I think it'll make a lot of your headaches go away when coding this project.

Just a suggestion,
Sandra.

Any truly great code should be indisguishable from magic.
SandraD
20
Years of Service
User Offline
Joined: 30th May 2004
Location: Down on the corner, out in the street.
Posted: 11th Jun 2004 18:09 Edited at: 11th Jun 2004 18:11
Hello again,

Well, as it turns out, my last posting made a huge assumption which I've now discovered was in error. By that I mean, that DB has all the commands needed to manipulate the Binary behind the math contained in integers. As it turned out, something I've been working on with another needed this logic ability, which I found to my dismay that my DBC could not manage. I dunno if it's corrected in DBPro or not but hope it would be, however I offer up this little snippet of code in case it helps you in the effort;



I only did 8 bits because that was all I needed, but it should work as far out as 15 without problems. One thing yo have to watch out for is the sign of the number given the operation, which I did not allow for here but would normally be in bit 16.

Good luck with your attempt!
Sandra.

Any truly great code should be indisguishable from magic.
Cian Rice
20
Years of Service
User Offline
Joined: 8th Jun 2004
Location:
Posted: 12th Jun 2004 03:05 Edited at: 12th Jun 2004 03:06
Wanted to delete my message, that this is taking the place of, just ignore me...

Got anime?
I do.

Login to post a reply

Server time is: 2024-09-22 12:22:06
Your offset time is: 2024-09-22 12:22:06