Anyone know what the mathmatical calculation is to determine a Dimms "Page Size"?? I found this but it does not seem to work:
Page size = (2^col)*bus_width where, col = number of column address lines (SPD byte 4: Number of Column Addresses) bus_width = number of data(DQ) lines (???SPD byte 13: SDRAM Device Width???)
Thanks - Joe
Anyone know what the mathmatical calculation is to determine a Dimms "Page Size"?? I found this but it does not seem to work:
Page size = (2^col)*bus_width where, col = number of column address lines (SPD byte 4: Number of Column Addresses) bus_width = number of data(DQ) lines (???SPD byte 13: SDRAM Device Width???)
"device width" is the number of data lines per DRAM chip on your DIMM. This isn't the same as the number of data lines on the DIMM itself; that is 64 usually (not counting the ECC bits). This info is in the SPD as well.
Segher
Quoting Segher Boessenkool segher@kernel.crashing.org:
Anyone know what the mathmatical calculation is to determine a Dimms "Page Size"?? I found this but it does not seem to work:
Page size = (2^col)*bus_width where, col = number of column address lines (SPD byte 4: Number of Column Addresses) bus_width = number of data(DQ) lines (???SPD byte 13: SDRAM Device Width???)
"device width" is the number of data lines per DRAM chip on your DIMM. This isn't the same as the number of data lines on the DIMM itself; that is 64 usually (not counting the ECC bits). This info is in the SPD as well.
Segher
Ok, so that must be byte 6: Data Width of Assembly. It still does not seem to compute though.
col = 9 /* SPD byte 4: Number of Column Addresses */ bus_width = 64 /* SPD byte 6: Data Width of Assembly */
page_size = (2^col)*bus_width
5184 = 81 * 64
Which is not correct because the DIMM has a 4k page size. (According to it's datasheet).
Please Help.
Thanks - Joe
Quoting Segher Boessenkool segher@kernel.crashing.org:
Anyone know what the mathmatical calculation is to determine a Dimms "Page Size"?? I found this but it does not seem to work:
Page size = (2^col)*bus_width where, col = number of column address lines (SPD byte 4: Number of Column Addresses) bus_width = number of data(DQ) lines (???SPD byte 13: SDRAM Device
Width???)
"device width" is the number of data lines per DRAM chip on your DIMM. This isn't the same as the number of data lines on the DIMM itself; that is 64 usually (not counting the ECC bits). This info is in the SPD as well.
Segher
Ok, so that must be byte 6: Data Width of Assembly. It still does not seem to compute though.
col = 9 /* SPD byte 4: Number of Column Addresses */ bus_width = 64 /* SPD byte 6: Data Width of Assembly */
page_size = (2^col)*bus_width
2^9 = 512
5184 = 81 * 64
512 * 64 = 32K
Myles
Which is not correct because the DIMM has a 4k page size. (According to it's datasheet).
Please Help.
col = 9 /* SPD byte 4: Number of Column Addresses */ bus_width = 64 /* SPD byte 6: Data Width of Assembly */
page_size = (2^col)*bus_width
2^9 = 512
5184 = 81 * 64
512 * 64 = 32K
Myles
Sorry, that should have been 32K bits, since you are multiplying by 64 bits. Then dividing by 8 bits/byte = 4 KB.
Myles
Which is not correct because the DIMM has a 4k page size. (According to it's datasheet).
Quoting Myles Watson myles@pel.cs.byu.edu:
col = 9 /* SPD byte 4: Number of Column Addresses */ bus_width = 64 /* SPD byte 6: Data Width of Assembly */
page_size = (2^col)*bus_width
2^9 = 512
5184 = 81 * 64
512 * 64 = 32K
Myles
Sorry, that should have been 32K bits, since you are multiplying by 64 bits. Then dividing by 8 bits/byte = 4 KB.
Myles
Which is not correct because the DIMM has a 4k page size. (According to it's datasheet).
Your right, Duh I was doing 9^2 = 81 :-)
col = 9 /* SPD byte 4: Number of Column Addresses */ bus_width = 64 /* SPD byte 6: Data Width of Assembly */
bit_page_size = ((2^col) * bus_width)
*/ convert to KB */ page_size = ((bit_page_size / 8) >> 10)
= 4KB
Sweet, this is a much easier way to calculate the DRA ? DRAM Row Attribute Register!! One last question, A normal SDRAM DIMM should always have SPD byte 6 = 64 and ECC should have SPD byte 6 = 72. Is this correct??
Thanks for all the help - Joe
Ok, here is my DRA function for i82830 raminit.c. Feedback, suggestions welcome. If there is any easier way to write this please let me know. I am still a newbie at C, but learning quickly. If the format looks funky, blaime Horde IMAP.
Thanks - Joe
----------------------------------------------
static void set_dram_row_attributes(const struct mem_controller *ctrl) { int i, dra, col, width, page_size;
for (i = 0; i < DIMM_SOCKETS; i++) { /* First check if a DIMM is actually present. */ if (smbus_read_byte(ctrl->channel0[i], 2) == 4) { print_debug("Found DIMM in slot "); print_debug_hex8(i); print_debug(", Setting DRA...\r\n");
dra = 0x00;
/* columns */ col = smbus_read_byte(ctrl->channel0[i], 4);
/* data width */ width = smbus_read_byte(ctrl->channel0[i], 6);
/* calculate page size in bits */ page_size = ((1 << col) * width);
/* convert to Kilobytes */ dra = ((page_size / 8) >> 10);
/* 2KB */ if (dra == 0x2) { dra = 0xF0; /* 4KB */ } else if (dra == 0x4) { dra = 0xF1; /* 8KB */ } else if (dra == 0x8) { dra = 0xF2; /* 16KB */ } else if (dra == 0x10) { dra = 0xF3; } else { print_debug("Page Size not supported\r\n"); die("HALT!\r\n"); } } else { print_debug("No DIMM found in slot "); print_debug_hex8(i); print_debug(", Setting DRA to 0xFF\r\n");
/* If there's no DIMM in the slot, set dra value to 0xFF. */ dra = 0xFF; }
/* Set the value for DRAM Row Attribute Registers */ pci_write_config8(ctrl->d0, DRA + i, dra); print_debug("DRA "); print_debug_hex8(DRA + i); print_debug(" has been set to "); print_debug_hex8(dra); print_debug("\r\n"); } }
Joseph Smith wrote:
Ok, here is my DRA function for i82830 raminit.c. Feedback, suggestions welcome. If there is any easier way to write this please let me know. I am still a newbie at C, but learning quickly. If the format looks funky, blaime Horde IMAP.
Thanks - Joe
Looks good, does it work? I was going to suggest using binary shift to get rid of all the if-else's but turns out it has a bunch of faults of its own...
-Corey
PS Sorry about my last email, I shouldn't write emails when I'm this tired, I sounded like an a**hole. Probably do in this one too.
On Fri, Jul 13, 2007 at 01:44:52AM -0400, Joseph Smith wrote:
/* convert to Kilobytes */ dra = ((page_size / 8) >> 10);
Please don't use bit shifting for multiplication and division.
page_size / 8 / 1024
is nicer to read, and the compiler will probably optimize both statements to a single >> 13 anyway.
Note also that you're now using the dra variable to hold something very different from the DRA value, while the rest of the function pretty much has one variable for each register. Variables (ie registers) are scarce during RAM init so I think re-use is good.
/* 2KB */ if (dra == 0x2) { dra = 0xF0; /* 4KB */ } else if (dra == 0x4) { dra = 0xF1; /* 8KB */ } else if (dra == 0x8) { dra = 0xF2; /* 16KB */ } else if (dra == 0x10) { dra = 0xF3; } else { print_debug("Page Size not supported\r\n"); die("HALT!\r\n"); }
This could also be a switch:
switch(dra) { case 2: dra=0xf0; break; case 4: dra=0xf1; break; case 8: dra=0xf2; break; case 16: dra=0xf3; break; default: print_debug("incompatible\n"); die("bye"); }
But I think this is simpler:
dra = log2(dra); if (dra > 3) { print_debug("incompatible\n"); die("bye"); } dra |= 0xf0;
//Peter
* Peter Stuge peter@stuge.se [070713 12:16]:
On Fri, Jul 13, 2007 at 01:44:52AM -0400, Joseph Smith wrote:
/* convert to Kilobytes */ dra = ((page_size / 8) >> 10);
Please don't use bit shifting for multiplication and division.
I think this is a bad dogma. Using shifts for mul/div is pretty obvious to understand and almost courteous.
On Fri, Jul 13, 2007 at 12:38:02PM +0200, Stefan Reinauer wrote:
dra = ((page_size / 8) >> 10);
Please don't use bit shifting for multiplication and division.
I think this is a bad dogma. Using shifts for mul/div is pretty obvious to understand and almost courteous.
Or it's human adapting to machine rather than the other way around.
Personally, I adapted long ago so I like shifts too, but not everyone does. It touches on "Encapsulate and isolate assembly language" in the coding guidelines.
RAM init is many bits back and forth anyway though, so if we need to pick just one piece of code where it's OK, that would be it.
//Peter
Quoting Peter Stuge peter@stuge.se:
On Fri, Jul 13, 2007 at 01:44:52AM -0400, Joseph Smith wrote:
/* convert to Kilobytes */ dra = ((page_size / 8) >> 10);
Please don't use bit shifting for multiplication and division.
page_size / 8 / 1024
is nicer to read, and the compiler will probably optimize both statements to a single >> 13 anyway.
Quoting Stefan Reinauer stepan@coresystems.de: I think this is a bad dogma. Using shifts for mul/div is pretty obvious to understand and almost courteous.
So which way is correct in linuxbios standards?
Note also that you're now using the dra variable to hold something very different from the DRA value, while the rest of the function pretty much has one variable for each register. Variables (ie registers) are scarce during RAM init so I think re-use is good.
Yup, DRA is the registers address, and dra is it's value.
But I think this is simpler:
dra = log2(dra); if (dra > 3) { print_debug("incompatible\n"); die("bye"); } dra |= 0xf0;
What does the log2 function do? And in what file does it live?
Thanks - Joe
On Fri, Jul 13, 2007 at 07:21:47AM -0400, Joseph Smith wrote:
Quoting Peter Stuge peter@stuge.se:
Please don't use bit shifting for multiplication and division.
Quoting Stefan Reinauer stepan@coresystems.de: I think this is a bad dogma. Using shifts for mul/div is pretty obvious to understand and almost courteous.
So which way is correct in linuxbios standards?
I guess either. :)
Yup, DRA is the registers address, and dra is it's value.
Point was that dra held bank kb size.
dra = log2(dra); if (dra > 3) { print_debug("incompatible\n"); die("bye"); } dra |= 0xf0;
What does the log2 function do?
base-2 logarithmic function
It returns the position of the leftmost 1 bit in the LE parameter.
log2(1) = 0 log2(2) = 1 log2(4) = 2 log2(8) = 3 etc
It is actually not sufficient though, since it's integer only in romcc. Check that the kb page size is valid before calling log2(), but it can still be used to conveniently calculate the needed value.
And in what file does it live?
src/arch/i386/include/arch/romcc_io.h
There's also one version in util/romcc/tests/simple_test5.c that uses __builtin_bsr() which compiles directly to the bsr opcode.
//Peter
Anyone know what the mathmatical calculation is to determine a Dimms "Page Size"?? I found this but it does not seem to work:
Page size = (2^col)*bus_width where, col = number of column address lines (SPD byte 4: Number of Column Addresses) bus_width = number of data(DQ) lines (???SPD byte 13: SDRAM Device Width???)
"device width" is the number of data lines per DRAM chip on your DIMM. This isn't the same as the number of data lines on the DIMM itself; that is 64 usually (not counting the ECC bits). This info is in the SPD as well.
Ok, so that must be byte 6: Data Width of Assembly.
Yes.
It still does not seem to compute though.
col = 9 /* SPD byte 4: Number of Column Addresses */ bus_width = 64 /* SPD byte 6: Data Width of Assembly */
page_size = (2^col)*bus_width
5184 = 81 * 64
Which is not correct because the DIMM has a 4k page size.
2**9 * 64 = 512 * 64 = 32k bits = 4kB.
Segher