code logs -> 2007 -> Mon, 29 Oct 2007< code.20071028.log - code.20071030.log >
--- Log opened Mon Oct 29 00:00:26 2007
00:40 gnolam [lenin@Nightstar-10613.8.5.253.static.se.wasadata.net] has quit [Quit: Z?]
00:42
<@ToxicFrog>
aaaaaaaaaaah
00:42
<@ToxicFrog>
Goddamnit, Java
00:42
<@ToxicFrog>
class Foo { public static int thingy = 0; }
00:43
<@ToxicFrog>
class Bar extends Foo { public static final int thingy = 8; }
00:43
<@ToxicFrog>
print(new Bar().thingy) => 0
00:44
<@McMartin>
... that should actually be a warning.
00:44
<@McMartin>
Try removing the "static"s.
00:44
<@ToxicFrog>
Well, it's actually private and wrapped in a getThingy() method.
00:44
<@McMartin>
Yeah, but doing virtual dispatch on a static method is supposed to be a warning.
00:45
<@McMartin>
I forget whether there's an actual hole in the spec there or not, though.
00:46
<@ToxicFrog>
Aah.
00:46
<@ToxicFrog>
More specifically, what I actually want it to do is this:
00:46
<@McMartin>
In C++, if you go Foo *A = new Bar(); cout << a->thingy in that case it will give you 0 and the C++ spec demands it.
00:46
<@McMartin>
Any reason you can't just have getThingy() return 8 directly?
00:47
<@ToxicFrog>
Well, I have a superclass, which has getThingy().
00:47
<@ToxicFrog>
I have a bunch of subclasses that all return different, but hard-coded, values.
00:47
<@ToxicFrog>
I was hoping I could just do:
00:47 You're now known as TheWatcher[T-2]
00:47
<@ToxicFrog>
public int getThingy() { return thingy; }
00:47
<@ToxicFrog>
And override the default value of thingy in all the subclasses.
00:48
<@ToxicFrog>
However, it always returns the default value of thingy as stated in the superclass.
00:48
<@McMartin>
Ah.
00:48
<@McMartin>
So, make it non-static, and set it in the subclasses' constructors.
00:50 You're now known as TheWatcher[zZzZ]
00:50
<@ToxicFrog>
Making it nonstatic seems counterintuitive, as it is not in fact an instance variable.
00:50
<@ToxicFrog>
Ideally it would be a constant static.
00:51
<@McMartin>
Except that you access a static variable with MOV AX, [ConstantMemoryAddress].
00:52
<@ToxicFrog>
Provided that ConstantMemoryAddress is different for each subclass, I don't see how this is a problem.
00:54
<@McMartin>
But you don't know the subclass until runtime.
00:55
<@McMartin>
Now, I'd think that new Bar() would say "I am of type Bar"
00:55
<@McMartin>
But I know C++ used how the variable was declared to resolve nonvirtuals
00:56
<@ToxicFrog>
The implication here appears to be that if I go:
00:56
<@ToxicFrog>
Foo tmp = new Bar();
00:56
<@ToxicFrog>
I will get Foo's statics, not Bar's.
00:56
<@ToxicFrog>
Unless I explicitly downcast it before playing with it.
00:56
<@McMartin>
Yes.
00:56
<@McMartin>
At least in C++.
00:57
<@McMartin>
In Java, that's supposed to be a warning "Attempted to access a static field through a variable".
00:57
<@ToxicFrog>
That would explain the behaviour I'm seeing here.
00:57
<@McMartin>
Oh, right, becuase getThingy() is defined once.
00:57
<@ToxicFrog>
And recall that I'm not accessing the static directly, I'm calling the static method getThingy() on a variable of type Foo, which holds a Bar.
00:57
<@McMartin>
Yeah
00:58
<@McMartin>
And is, in fact, probably expanding "return thingy;" to "return Foo.thingy;".
00:58
<@McMartin>
Hence, no warning.
00:59
<@ToxicFrog>
Joy.
01:04
<@ToxicFrog>
Hmm. How do I initialize finals?
01:05
<@McMartin>
One of two ways.
01:05
<@McMartin>
(a) at the declaration
01:05
<@ToxicFrog>
class Foo extends Bar { private final int thingy = 1; } compiles, but doesn't actually work (getThingy() still returns 0)
01:05
<@McMartin>
(b) In the constructor. The JVM insists that every path through a construct assign a final exactly once.
01:06
<@McMartin>
I think you want thingy to be protected, not private.
01:06
<@McMartin>
Since if it's private, Bar.getThingy() can't see it.
01:06
<@ToxicFrog>
Oh right.
01:06
<@McMartin>
And, of course, it has to be nonstatic in Bar, too.
01:06
<@ToxicFrog>
Yeah.
01:07
<@ToxicFrog>
Ok, it's now declared as "protected final int" in the superclass and all three subclasses, and there's still no dice.
01:10
<@McMartin>
What if it's not final in the superclass?
01:10
<@McMartin>
I'm surprised it didn't error at you for that one.
01:10
<@McMartin>
I mean, you're subclassing something that you're explicitly saying, with final, cannot be subclassed.
01:21
<@ToxicFrog>
Still doesn't work.
01:22
<@McMartin>
Mmf.
01:22
<@McMartin>
Wait
01:22
<@McMartin>
Where are you calling getThingy()?
01:25
<@ToxicFrog>
From main:
01:25
<@ToxicFrog>
Foo tmp = new Bar();
01:25
<@ToxicFrog>
System.out.println(tmp.getThingy());
01:26
<@ToxicFrog>
Foo contains the definition of getThingy(), and protected static int thingy; Bar extends Foo and contains protected static int thingy = 1;
01:29
<@ToxicFrog>
Aah, screw it, elegance isn't worth any marks in this course, I'll just overload getThingy()
01:40
<@McMartin>
Um, I note the "static" is still there.
01:42
<@ToxicFrog>
Er.
01:42
<@ToxicFrog>
That's a typo.
01:42
<@ToxicFrog>
It's not there in the actual code.
01:42
<@McMartin>
OK
01:55 Vornicus [~vorn@ServicesOp.Nightstar.Net] has quit [Ping Timeout]
03:24 GeekSoldier|bed [~Rob@Nightstar-4575.pools.arcor-ip.net] has quit [Ping Timeout]
03:49 ToxicFrog [~ToxicFrog@Admin.Nightstar.Net] has quit [Operation timed out]
03:50 ToxicFrog [~ToxicFrog@Admin.Nightstar.Net] has joined #code
03:50 mode/#code [+o ToxicFrog] by ChanServ
04:40 GeekSoldier|bed [~Rob@Nightstar-4575.pools.arcor-ip.net] has joined #code
04:41 ChalcyAFK [~Chalcedon@Nightstar-2310.ue.woosh.co.nz] has quit [Quit: Gone]
05:18 Thaqui [~Thaqui@Nightstar-13312.jetstream.xtra.co.nz] has joined #code
05:18 mode/#code [+o Thaqui] by ChanServ
05:58 GeekSoldier|bed [~Rob@Nightstar-4575.pools.arcor-ip.net] has quit [Connection reset by peer]
07:48 Vornicus [~vorn@Admin.Nightstar.Net] has joined #code
07:48 mode/#code [+o Vornicus] by ChanServ
08:59 AnnoDomini [AnnoDomini@Nightstar-29599.neoplus.adsl.tpnet.pl] has quit [Quit: If nothing we do matters, all that matters is that we do.]
09:02 AnnoDomini [AnnoDomini@Nightstar-29599.neoplus.adsl.tpnet.pl] has joined #Code
09:02 mode/#code [+o AnnoDomini] by ChanServ
09:08 You're now known as TheWatcher
10:19 MyCatSchemes [~rb6822@Nightstar-23340.cs.bris.ac.uk] has joined #code
10:49 GeekSoldier|bed [~Rob@Nightstar-4218.pools.arcor-ip.net] has joined #code
10:52 GeekSoldier|bed is now known as GeekSoldier|work
11:49 GeekSoldier|work [~Rob@Nightstar-4218.pools.arcor-ip.net] has quit [Ping Timeout]
11:55 MyCatSchemes [~rb6822@Nightstar-23340.cs.bris.ac.uk] has quit [Client exited]
12:59 gnolam [lenin@Nightstar-10613.8.5.253.static.se.wasadata.net] has joined #Code
12:59 mode/#code [+o gnolam] by ChanServ
14:23
<@ToxicFrog>
...hmm. I'm not sure if this is a design flaw or not.
14:46
<@ToxicFrog>
PHase 4 is to implement a pipelined version of our CPU, but I think we've designed a CPU that cannot be pipelined.
14:51 GeekSoldier|work [~Rob@Nightstar-5528.pools.arcor-ip.net] has joined #code
15:03 GeekSoldier|work is now known as GeekSoldier
15:27
<@gnolam>
... sounds like a design flaw to me.
15:43
<@ToxicFrog>
The reason it can't be pipelined, though, is that all instructions execute in one clock cycle.
15:43
<@ToxicFrog>
There's no room to speed that up.
15:50
<@gnolam>
Split it into fetch/execute and clock it higher?
16:04
<@Vornicus>
What instructions do you have?
17:08 You're now known as TheWatcher[afk]
17:14 AnnoDomini [AnnoDomini@Nightstar-29599.neoplus.adsl.tpnet.pl] has quit [Ping Timeout]
17:14 Attilla [~The.Attil@194.72.70.ns-11849] has quit [Quit: <Insert Humorous and/or serious exit message here>]
17:21
<@ToxicFrog>
Vornicus: add, subtract, shift, bitwise logic, conditional and unconditional jumps, register<->register and register<->memory transfers.
17:21 AnnoDomini [AnnoDomini@Nightstar-29486.neoplus.adsl.tpnet.pl] has joined #Code
17:21 mode/#code [+o AnnoDomini] by ChanServ
17:21
<@ToxicFrog>
gnolam: as it is, it fetches on the rising edge and executes on the falling edge.
17:23
<@Vornicus>
...huh. yeah, I don't see much you can do to speed that up.
17:23
<@Vornicus>
or, pipeline it, rather
17:23
<@Vornicus>
I mean, unless you are running a RISC architecture, in which case you could "pipeline" in the sense that you can execute on parallel registers.
17:27
<@ToxicFrog>
It is RISC.
17:28
<@ToxicFrog>
In that it has a small set of fast instructions which can be used as building blocks, and all instructions are either register-to-register or load-store.
17:28
<@Vornicus>
RISC I thought also did the "lots of registers" thing.
17:29
<@ToxicFrog>
We have as many registers as we had room for without compromising the fetch operation - 8, one of which is dedicated to PC.
17:30
<@Vornicus>
Which if you can run simultaneous commands (hard) you can get multiple calculations going on at once.
17:30
<@Vornicus>
What is this, an 8-bit machine?
17:30
<@ToxicFrog>
16-bit, kind of.
17:30
<@Vornicus>
kind of?
17:30
<@ToxicFrog>
16-bit data lines and registers, but you're only guaranteed to be able to address 9 bits of 2-aligned memory.
17:31
<@ToxicFrog>
In theory you can go up to 16 bits of 2-aligned, but it requires cleverness.
17:31
<@Vornicus>
half a k.
17:31
<@Vornicus>
Cool.
17:31
<@ToxicFrog>
1K.
17:31
<@Vornicus>
ah, so. 2-aligned, yadda yadda.
17:31
<@ToxicFrog>
Each address is 2 bytes.
17:32
<@Vornicus>
What's your instruction size?
17:32
<@ToxicFrog>
128K using LOADP and STOREP, but proper use of those is nontrivial.
17:32
<@ToxicFrog>
(PC is a full 16 bits, though; you could always just reserve the upper 127K for code)
17:33
<@ToxicFrog>
16 bits.
17:33
<@ToxicFrog>
9 bits is the most we could cram in there without excessively restricting either instruction set or register count.
17:33
<@ToxicFrog>
We could have made it 32, but that means fetch takes two clocks, since we're limited to 16-bit buses.
17:33
<@Vornicus>
I don't get the 9 bits thing?
17:34
<@ToxicFrog>
LOAD takes a register and a memory address, as does STORE
17:34
<@Vornicus>
Ah
17:34
<@Vornicus>
And loadp/storep ask a pointer?
17:34
<@ToxicFrog>
3 bits for the register, 4 bits for the instruction class and the opcode, leaves you with 9 for the address.
17:34
<@ToxicFrog>
LOADP/STOREP take two registers, and read a pointer from one of them.
17:35
<@ToxicFrog>
So you can get a full 16 bits of address space, provided that all your addresses over 9 bits are in registers when you need them.
17:35
<@Vornicus>
Do you have a SET instruction?
17:36
<@ToxicFrog>
Yes, but it too is limited to 9 bits; so in practice you use SET, SHIFT, and OR, which means accessing high memory requires up to 10 cycles and two registers.
17:36
<@ToxicFrog>
A smart compiler would create a table of useful addresses in low memory.
17:36 * Vornicus would actually do instruction/register/byteflag/8bits
17:37
<@ToxicFrog>
Which means you can then use LOAD followed by LoaDP/STOREP
17:37
<@ToxicFrog>
"byteflag"?
17:37
<@Vornicus>
Yeah
17:37
<@Vornicus>
Have a flag that says whether you're setting the high byte or the low one.
17:39
<@Vornicus>
MMIX sorta does it this way - you can set only 16 bits of a register at a time from literal, but there's distinct instructions for each of the four 16-bit chunks of the 64-bit register.
17:40
<@Vornicus>
You can even extend this to your load/store thing, if you're willing to page.
17:41
<@Vornicus>
not page, bank switch.
17:43
<@ToxicFrog>
Hmm. That's a good idea, actually.
17:43
<@ToxicFrog>
Bank switching, if implemented at all, would be part of the MMU, not the CPU.
17:44
<@ToxicFrog>
But LOADH/LOADL would be handy, and we are allowed to revise the instruction set.
17:45
<@ToxicFrog>
Now, how to implement that...
17:45
<@Vornicus>
I don't know if it's proper to call it bank switching, even. What you do is you have a special register (or two, one for read and the other for write) that you write to via a flagged load or store, that when you do a load or store from literal, it adds that in as the high byte.
17:45
<@ToxicFrog>
I'm not sure it can be done with just the ALU, we may need a special module for it.
17:46
<@ToxicFrog>
Hmm. Also a possibility, but not one I think we'll be implementing; we want to keep things simple.
17:46
<@ToxicFrog>
I'll bounce that idea off the group, though.
17:46
<@Vornicus>
what's loadh/loadl do?
17:46
<@ToxicFrog>
SETH/SETL, rather
17:46
<@ToxicFrog>
Set high and low byte of register.
17:47
<@Vornicus>
What this would mean is that you lose 1 bit from immediate set.
17:47
<@ToxicFrog>
Yeah, but you'd need multiple instructions to set a complete register anyways.
17:47
<@Vornicus>
Which slows you down in the range from 256..512
17:47
<@Vornicus>
But it speeds you up in the range from 512 on.
17:48
<@ToxicFrog>
Yeah. Worth it, IMO.
17:48 Attilla [~The.Attil@194.72.70.ns-11849] has joined #code
17:50 * Vornicus eyes
17:51
<@ToxicFrog>
?
17:51
<@Vornicus>
Indeed, because your shifts and adds and ors can only manage, what, 5 bit literals, from 16384 on you gain /2/ cycles.
17:51
<@ToxicFrog>
They don't use literals, period.
17:51
<@ToxicFrog>
They are all register -> register -> ALU - register
17:51
<@Vornicus>
aha
17:52
<@Vornicus>
And you're thinking in haskell again. Stop that, you're confusing me. :)
17:52
<@ToxicFrog>
(as far as the special bank switch register goes: this costs us another register and we only have 7 user registers. I think this gets put into the MMU, at memory address 0 or something)
17:54
<@Vornicus>
I'm not so sure about that whole thing anyway
17:56
<@ToxicFrog>
The question is, is it more useful than LOADP/STOREP
17:56
<@ToxicFrog>
And I think it may be.
17:57
<@ToxicFrog>
Since, for accessing high memory, it reduces access times by a cycle if you're repeatedly accessing the same bank, and doesn't make things any worse if you aren't.
17:57
<@Vornicus>
But if all your arithmetic and bitwise and so forth operators are registers to register, you should be able to cram another couple of instructions in there - by my count it gives you as many as 7 bits for the extended instruction.
17:57
<@ToxicFrog>
Yes, but how does cramming in more instructions help?
18:00 Vornicus [~vorn@Admin.Nightstar.Net] has quit [Ping Timeout]
18:02 Vornicus [~vorn@ServicesOp.Nightstar.Net] has joined #code
18:02 mode/#code [+o Vornicus] by ChanServ
18:02
<@ToxicFrog>
Yes, but how does cramming in more instructions help?
18:02
<@Vornicus>
Well, in the arithmetic case it means you can get pipelining by adding in more complicated operators.
18:02
<@Vornicus>
:P
18:03
<@ToxicFrog>
Um no.
18:03
<@ToxicFrog>
(although we do have a free ALU slot)
18:03
<@Vornicus>
<Vornicus> But at the same time you need loadp/storep, because you're not going to be able to cram it all in code every time.
18:03
<@Vornicus>
I also said that when I got peered.
18:05
<@ToxicFrog>
Hmm. This is a true thing.
18:05
<@Vornicus>
I mean, how the hell do you use pointers without them?
18:06
<@Vornicus>
(and thus anything fancier than arrays)
18:06
<@Vornicus>
oh, no, I know: self-modifying code. :)
18:07
<@ToxicFrog>
That's what I typed, before the wireless went blooey again
18:07
<@ToxicFrog>
Or rather, still.
18:08
<@Vornicus>
Heh
18:10
<@Vornicus>
I think using the bankswitching mode you'll want a... how do I put this?
18:11
<@Vornicus>
You'll want to always be able to access the zero page.
18:11
<@Vornicus>
So load and store using the bank switcher would lose one bit to a flag.
18:12
<@ToxicFrog>
I'm ot sure if this is a problem with the hardware or with the driver, but the new laptop is way more sensitive to wobbly access points
18:12
<@ToxicFrog>
I should install the windows driver through ndiswrapper and see if it does any better
18:14
<@Vornicus>
Out of curiosity - would I be able to get your CPU docs?
18:16
<@ToxicFrog>
There aren't many docs to get as yet, just the instruction set reference - which has been rendered obsolete by this discussion
18:16
<@ToxicFrog>
But sure, one momenry
18:16
<@Vornicus>
Well, yeah, but
18:18
<@Vornicus>
(that's also what I was looking for, so I could examine it more closely)
18:20
<@Vornicus>
man, neooffice is sloooooow
18:28
<@Vornicus>
Other things I would consider: you have enough room for an extended shift operator, since the maximum sensical shift is 16.
18:30
<@Vornicus>
Then, documentation errors: BNV references the CCR "V" bit, which doesn't exist. Also, I don't see a way of reading the overflow bit.
18:32
<@Vornicus>
LOADI's bit code should use v instead of m
18:44 You're now known as TheWatcher
18:54
<@ToxicFrog>
BNV should check N, and there should be a BO instruction or similar
18:54
<@ToxicFrog>
Also, dammit.
18:54
<@ToxicFrog>
Installed ndiswrapper, installed windows driers
18:55
<@ToxicFrog>
One driver failed to initialize. The other initialized fine, but refused to connect to anything.
19:01 GeekSoldier is now known as GeekSoldier|bed
19:53
<@Vornicus>
Windows driers... I think I'd prefer my clothes to be prepared for wearing by something a bit more reliable...
19:55
<@Vornicus>
:P
19:56
<@Vornicus>
On the other hand nothing seems to /set/ O, so no worries
19:57
<@Vornicus>
or something
19:58
<@Vornicus>
The only three operations that can cause overflow - ADD, SUB, and SL, set C instead of O.
19:59
<@Vornicus>
Perhaps you don't have it because you don't need it, and should just get rid of that flag from the BCC
19:59
<@Vornicus>
er, CCR
20:02
<@Vornicus>
if you did MUL and DIV you'd need an O, as you would end up carrying far more than one bit.
21:01 GeekSoldier|bed [~Rob@Nightstar-5528.pools.arcor-ip.net] has quit [Ping Timeout]
22:10
<@ToxicFrog>
Yeah. The CCR definition is still kind of fuzzy.
22:10
<@ToxicFrog>
At any rate, we've now blocked out the CPU internals, and created a table of control module outputs.
22:11
<@ToxicFrog>
All that's left in the design phase is the control module's internal structure.
22:14
<@ToxicFrog>
We also replaced LOADI with SETH/SETL as suggested, and determined that we can replace CMP with an entire set of instructions that perform some ALU operation but only update CCR.
22:50
<@Vornicus>
What do you mean by that last bit?
23:00
<@ToxicFrog>
Well, CMP is basically SUB except only the CCR is updated, the result of the calculation isn't stored.
23:01
<@ToxicFrog>
The way we modified CMP, it is now possible (with no extra effort on our part, even) to emit machine code that performs any ALU operation, updates the CCR, and doesn't store the result.
23:01
<@Vornicus>
Sweet. What'd you do?
23:02
<@ToxicFrog>
Grabbed one of the spare bits in that instruction format and make it ?rLE, rLE being the load-enable line for the register bank.
23:06
<@Vornicus>
ah, so
23:06
<@Vornicus>
I was going to suggest doing that to make one of the inputs to the instruction a literal, but with only 3 bits it gets useless.
23:07
<@ToxicFrog>
Yeah.
23:07
<@ToxicFrog>
If you want a literal, you do SETH SETL first.
23:32 You're now known as TheWatcher[T-2]
23:34 You're now known as TheWatcher[zZzZ]
23:39 gnolam [lenin@Nightstar-10613.8.5.253.static.se.wasadata.net] has quit [Quit: Z?]
23:43 Vornotron [~vorn@64.148.20.ns-11236] has joined #code
23:45 Vornicus [~vorn@ServicesOp.Nightstar.Net] has quit [Ping Timeout]
23:45 Vornotron is now known as Vornicus
--- Log closed Tue Oct 30 00:00:33 2007
code logs -> 2007 -> Mon, 29 Oct 2007< code.20071028.log - code.20071030.log >