View unanswered posts | View active topics It is currently Thu Mar 28, 2024 10:23 am



Reply to topic  [ 108 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next
 One Page Computing - roll your own challenge 
Author Message

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
I'm not sure what you're seeing or why - perhaps you could show one or two worked examples?
Have you tried running the python emulator, or the javascript one? I think you see enough there to see what's going on.


Wed Sep 26, 2018 8:00 pm
Profile

Joined: Sat Jun 16, 2018 2:51 am
Posts: 50
I get this:
Attachment:
predTable.png
predTable.png [ 10.44 KiB | Viewed 11014 times ]

I'm trying to figure out how the architecture works from the verilog code...
In the python emulator, the line of code is still the same...
Code:
if (bool(pinvert) ^ bool(((pcarry or c) and (pzero or z)))):


Wed Sep 26, 2018 9:27 pm
Profile

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
Hmm - have you noticed there's pcarry, which controls whether the predicate as a whole is sensitive to c, and pzero, which controls whether the predicate is sensitive to z? In the originally quoted table, "Carry pred" refers to the value of pcarry, and same for zero. That is, the columns are the value of the predicate control bit, not the cpu status bit.

As ever, there might be ways to improve the doc.

For the casual onlooker, the idea is that we can do a unconditional operation such as ld, or one only when z is set, with ld.z, or only when z is clear, with ld.nz, and so on. There's the always condition, the nop condition, and six others, which turns out to be quite powerful and flexible. More importantly for one-page computing, it's quite simple.

(We had another goal, of small implementation size, so simple in the implementation is good too.)

In later revisions of the architecture, we could take the 'nop' case and reuse it as an opcode bit, which means we get to double the operation count, with half of them predicated and half of them not.


Wed Sep 26, 2018 9:39 pm
Profile

Joined: Sat Jun 16, 2018 2:51 am
Posts: 50
Ah I see. I was unaware of the instruction variation.

So, suppose you have instruction ld.z. pred_zero would be 1, pred_invert would be 0, and pred_carry would be 0. How will the predicate signal ever be high/true for the ld.z instruction? If,
Code:
predicate = pred_invert xor ( (pred_carry or flag_carry) and (pred_zero or flag_zero) )

Then the only way it can evaluate to true is if flag_carry is 1 ...

Thanks a lot for you time and patience!


Thu Sep 27, 2018 6:08 pm
Profile

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
For whatever subtle reason, it seems the pred bits are negative logic, so for a ld.z you'd have pred_zero as 0, pred_carry as 1, and pred_invert as 0. I think that should work out.

Of course, at assembly level you don't worry about this. But of course the verilog, the assembler, the emulators, the monitor do all need to do it. (For at least some of these CPUs, we wrote (hoglet wrote) a single-stepping disassembling monitor which runs on the CPU, and has to understand enough to disassemble and single step. It was all rather interesting! See here
https://github.com/hoglet67/opc/blob/ma ... /monitor.s
and
https://github.com/hoglet67/opc/tree/master/include
)


Thu Sep 27, 2018 9:01 pm
Profile

Joined: Sat Jun 16, 2018 2:51 am
Posts: 50
Ah ok! Thanks! I'll explore the programs as well =)


Thu Sep 27, 2018 10:54 pm
Profile

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
There are some arithmetic libraries too - see the 'syslib' files in
https://github.com/revaldinho/opc/tree/master/bcpl


Fri Sep 28, 2018 7:40 am
Profile

Joined: Sat Jun 16, 2018 2:51 am
Posts: 50
Hi folks!

I've created a schematic for OPC-6. A few signals have been renamed for readability. Let me know if you spot any errors or omissions and I will update accordingly.

Note: This schematic will not pass KiCad's electrical rule check. I've omitted the required bus signal labels in favor of readability.


Attachments:
OPC6.pdf [1.06 MiB]
Downloaded 480 times


Last edited by quadrant on Sat Oct 27, 2018 1:53 am, edited 1 time in total.

Sat Oct 27, 2018 1:49 am
Profile

Joined: Sat Jun 16, 2018 2:51 am
Posts: 50
I have a few lingering questions about OPC-6:

1) Clarification on the concept of "one word instructions" and their relation to the FSM? From the source code:
Code:
wire [15:0] operand = (IR_q[IRLEN]||IR_q[IRLD]||(op==INC)||(op==DEC)||(IR_q[IRWBK]))?OR_q:RF_w_p2; // One word instructions operand usu comes from RF

2) What is the purpose of each of the predicate variations (pred_d, pred_din, pred_q)?

3) I noticed in the emulator you only check for software interrupts. If you were to emulate hardware interrupts, what approach would you take?


Sat Oct 27, 2018 1:53 am
Profile

Joined: Tue Apr 25, 2017 7:33 pm
Posts: 32
quadrant wrote:
I have a few lingering questions about OPC-6:

1) Clarification on the concept of "one word instructions" and their relation to the FSM? From the source code:
Code:
wire [15:0] operand = (IR_q[IRLEN]||IR_q[IRLD]||(op==INC)||(op==DEC)||(IR_q[IRWBK]))?OR_q:RF_w_p2; // One word instructions operand usu comes from RF



From the OPC6 Spec:

All memory accesses are 16 bits wide and instructions are encoded in either one or two words ::

Code:
ppp l oooo ssss dddd  nnnnnnnnnnnnnnnn
  \  \   \    \   \           \_______ 16b optional operand word
   \  \   \    \___\__________________  4b source and destination registers
    \  \___\__________________________  1b instruction length + 4b opcode
     \________________________________  3b predicate bits           


A one word instruction requires only a single FETCH cycle, and so the operand will usually be taken from the register file unless it's a very short immediate.

A two word instruction requires a second FETCH to get the 16bit operand

These states are labelled FET0 and FET1 in the Verilog state machine, with FET1 usually being skipped for the majority of instructions.

Quote:
2) What is the purpose of each of the predicate variations (pred_d, pred_din, pred_q)?


Even though it's single page of code, OPC6 does have a short pipeline and the EXEC stage on one instruction overlaps with the FETCH of the next instruction to improve performance.

Consider instructions to be executed in sequence, A:B:C

1. If C is a single word instruction that is to be executed based on the flag states produced by A, then we need to know what condition needs to be satisfied (the predicate) and what is the status of the flags. This needs to be determined at the end of the fetch (FET0) for C, because we are deciding whether or not to EXECute C or just skip straight to the next instruction fetch. However, during FET0 for C, the predicate bits have not yet been latched into the Instruction Register, so the computation uses the predicate bits as they are currently on the databus vs the stable flag bits in the status register. This is labelled pred_din.

2. If C were a two word instruction, the we must complete the second fetch (FET1) for C whether or not the instruction is to be executed. In this case we need to check predicates against flag states at the end of the FET1 cycle. The flags (from instruction A) are still stable and in the status register, but now the predicate bits are no longer on the data bus which is holding the 16b operand instead. The predicate bits however have been latched into the Instruction Register now at the end of FET0. So, we need to compare the predicate bits in the IR this time then vs the stable flag bits in the status register. This is labelled pred_q.

3. Finally if C were a single word instruction and were conditional on the status of the flags at the end of B then we have a slight problem. Execution of B overlaps with the fetch of C, so that at the end of FET0 for instruction C, the flags have not yet been written into the status register by B. So, just as in the first case the predicate bits are on the data bus for C, but now we need to compare these against the yet-to-be-written flags which have just been computed in instruction B. ie we are comparing predicates against the flag data on the 'd' side of the status register rather than the 'q' side. This is labelled pred_d.


Quote:
3) I noticed in the emulator you only check for software interrupts. If you were to emulate hardware interrupts, what approach would you take?


This would just need a slightly larger emulator modelling more of a system than just the CPU and memory. Probably checking for a hardware interrupt at the start of every cycle would be adequate, and pseudo-randomly firing the interrupt during specific tests to log the results.

R.


Last edited by Revaldinho on Tue Nov 06, 2018 10:38 pm, edited 1 time in total.



Sun Oct 28, 2018 3:57 pm
Profile

Joined: Sat Jun 16, 2018 2:51 am
Posts: 50
I see, thanks for the explanation!


Mon Oct 29, 2018 6:02 pm
Profile

Joined: Sat Jun 16, 2018 2:51 am
Posts: 50
How does the assembler for OPC-6 handle padding? For example consider the following code:
Code:
GROUP0: BYTE 0xAA
GROUP1: BYTE 0x11, 0x22
Is a byte of zero inserted after the byte 0xAA to make GROUP0 equal to a multiple of 16? Thus the programmer has to keep this in mind to avoid unexpected bytes?


Tue Mar 19, 2019 11:06 pm
Profile

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
At a guess, as it's a word-oriented machine, all values in the assembly source will be interpreted as words. There are no bytes, unless you say it has 16-bit bytes - which amounts to the same thing.


Wed Mar 20, 2019 8:02 am
Profile

Joined: Tue Apr 25, 2017 7:33 pm
Posts: 32
quadrant wrote:
How does the assembler for OPC-6 handle padding? For example consider the following code:
Code:
GROUP0: BYTE 0xAA
GROUP1: BYTE 0x11, 0x22
Is a byte of zero inserted after the byte 0xAA to make GROUP0 equal to a multiple of 16? Thus the programmer has to keep this in mind to avoid unexpected bytes?


I think this is easily shown with an example

Code:
python opc6asm.py test.as test.hex
0000  0001                  GLOBAL1:        BYTE    0x01
0001  0201                  GLOBAL2:        BYTE    0x01, 0x02
0002  0201 0003             GLOBAL3:        BYTE    0x01, 0x02, 0x03
0004  0201 0403             GLOBAL4:        BYTE    0x01, 0x02, 0x03, 0x04



As Ed says, it's a word oriented machine but bytes can be handy use so the assembler processes BYTE statements line by line, packs two bytes to a word and pads out any odd number with a 0 byte.


Wed Mar 20, 2019 9:01 am
Profile

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
Ah, thanks - a worked example is worth a thousand guesses. So, I think we can say that the OPC-6 doesn't know about bytes, but the assembler - this particular assembler - does, and is little-endian too. I think we hooked up 8-bit ports to the low end of the word. And we do read and interpret srecords, I think, and had to decide how to handle a bytestream. I expect that was a little-endian approach too.


Wed Mar 20, 2019 1:44 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 108 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next

Who is online

Users browsing this forum: No registered users and 12 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software