olofk | Alright. First lines of documentation submitted for orpsocv3 | 00:54 |
---|---|---|
_franck_ | I pushed Marek's patches to openOCD on github | 01:42 |
_franck_ | you should test it and see how fast it goes | 01:42 |
_franck_ | he did a really great job | 01:42 |
_franck_ | (still have a patch from him improving usb blaster speed) | 01:43 |
stekern | http://pastebin.com/Lxpd9Nd1 | 06:45 |
stekern | juliusb: thanks for the explanation, so basically what you are saying is that an exception can't happen in a delay-slot except when the instruction in the delay-slot caused the exception | 08:07 |
stekern | that's probably fine, but I'd like to try to just mark the delay-slot and update epcr to the pc accordingly (i.e. if (delay-slot) epcr = pc - 4 else epcr = pc) | 08:13 |
stekern | because that sounds like a lot simpler logic to me | 08:13 |
stekern | I might be wrong, could be that that's not going to work | 08:14 |
stekern | but a final question to how it is implemented now, consider this: l.sfeqi r0,1; l.bf some_place; l.sw 1(r0),r0 | 08:18 |
stekern | what will epcr be set to? | 08:18 |
stekern | since you are only detecting delay-slots when branches are taken, right? | 08:18 |
-!- X-Scale` is now known as X-Scale | 08:46 | |
@juliusb | stekern: is that a coremark for the newly re-pipelined cappuccino? | 10:32 |
stekern | yup, running at 80MHz on atlys | 10:33 |
stekern | I get the same score on de0-nano | 10:33 |
@juliusb | ahh 80, very nice though, 1.5coremarks :) | 10:34 |
stekern | it's actually slightly slower than the old cappuccino | 10:34 |
@juliusb | i thought it was 50MHz and somehow you'd gotten 2.4 | 10:34 |
@juliusb | oh right, but synthesises faster?> | 10:34 |
stekern | I get ~75 coremark when running 50MHz | 10:34 |
@juliusb | cool | 10:35 |
stekern | it's expected, load/stores are still kind of handled like in old cappucino | 10:36 |
@juliusb | regarding EPCR, thoguh | 10:36 |
stekern | I'm happy it scales linearly with the cpu-freq, that means working towards increasing fmax wasn't in vain ;) | 10:37 |
@juliusb | yes, only thing which can cause an exception in delay slot is thta instruction, otherwise PIC and timer are held off until that instruction completes (ie the padv signals go high, I think for execute stage, causing the writeback to occur) | 10:37 |
@juliusb | regarding trying the new EPCR calculation, by all means, go ahead and try it - that's what the regression test suite is for :) | 10:38 |
@juliusb | for your example, EPCR would point to the l.bf some_place insn because it was the insn in the delay slot causing alignment exception | 10:38 |
@juliusb | if you weren't branching, then EPCR points to l.sw | 10:39 |
@juliusb | it's not a delay slot | 10:39 |
@juliusb | it's the next instruction | 10:39 |
@juliusb | that's my understanding anyway | 10:39 |
@juliusb | there's no point re-evaluting the l.bf because it won't change because the flag won't have changed | 10:39 |
stekern | well, it _is_ a delay-slot regardless of if the branch have been taken or not, if that definition has any practical difference is another story | 10:47 |
stekern | btw, in my example, i wasn't branching ;) | 10:55 |
stekern | the definition is not so important though, I'm mostly interested in simplifying the logic, ctrl_branch_occur is pretty critical, so if we can avoid using that wherever possible, I reckon it's good | 10:58 |
stekern | but it's a bit weird if my example (l.sfeqi r0,1; l.bf some_place; l.sw 1(r0),r0) isn't handled consistantly | 10:59 |
stekern | juliusb: (there's no point re-evaluting the l.bf) but there's really no harm neither, right? | 11:41 |
stekern | I'm just fishing for a "yeah, but have you thought about this!?" here, before I start poking ;) | 11:42 |
@juliusb | my interpretation is that it becomes the delay slot when you are taking the branch, otherwise it's just the next instruction | 12:28 |
@juliusb | and yes, I realised I hadn't fully thought through your example until after I typed what I did, but in any case it's worth while talking through both cases | 12:29 |
@juliusb | :) | 12:29 |
stekern | speak first, think later, that's the way to do it! ;) | 12:29 |
@juliusb | totally | 12:29 |
@juliusb | what do you mean your example isn't handled consistently? | 12:29 |
@juliusb | basically, in a pipelined design, you're going to be evaluating the branch instruction (if it's a conditional branch) as you're getting ready to process the delay slot | 12:30 |
stekern | I mean if I change the logic so that a delay slot is always a delay slot, regardless if the branch was taken or not | 12:30 |
@juliusb | (whether it becomes officially a delay slot instruction or not depends on whether the branch is taken, so it's a bit annoying) | 12:30 |
@juliusb | well, I argue that's not good | 12:31 |
stekern | so perhaps the definition is important after all | 12:31 |
@juliusb | and I have designed it so that if you're about to take a branch, the only way you can get into a situation where you'll get an exception with the PC in the delay slot is if that delay slot instruction causes the exception | 12:31 |
@juliusb | in that case, you must have EPCR pointing to the preceeding instruction | 12:32 |
@juliusb | and if it's a tick or PIC exception during the delay slot, then you should finish the delay slot instruction and (supposing it doesn't cause an exception) set EPCR to the new branch location and service the tick/PIC exception | 12:33 |
stekern | yes, but that only holds for your definition of a delay slot | 12:33 |
@juliusb | but if it's not a delay slot (ie the conditional branch isn't being taken) and the instruction causes an exception then the EPCR should point to that instruction, not the preceeding branch | 12:34 |
stekern | I'm not saying my definition is 100% right, that's just how I have thought about it | 12:34 |
@juliusb | yep, fair enough | 12:34 |
stekern | some 3rd part, please chime in! ;) | 12:34 |
@juliusb | :) | 12:34 |
@juliusb | so, I think my way is going to be most efficient execution wise because you're not re-executing a branch you know you won't take | 12:34 |
@juliusb | however, my way may not be most efficient implementation wise because you need logic to account for that situation | 12:35 |
@juliusb | i'm quite sure, though, that the delay slot only exists when a branch is being taken, otherwise that following instruction is just the next instruction | 12:35 |
stekern | I mean, you could think of a l.bf as a 2-way branch instruction, one way going to some_place and the other is going to pc+8 | 12:35 |
@juliusb | mmm, you could, but I prefer thinking of it the other way, which just takes a branch or not, other wise your nice, simple linear execution continues | 12:36 |
@juliusb | so, I guess this doesn't matter except for the case you've brought up | 12:37 |
stekern | yeah, probably not | 12:37 |
@juliusb | which actually doesn't matter whether EPCR points to the branch or not | 12:37 |
@juliusb | so long as the flag remains the same | 12:38 |
@juliusb | which it should | 12:38 |
stekern | and I'm not sure that actually matter in practice neither | 12:38 |
@juliusb | well, it must, if you're going to re-play that bit of code and expect the same execution path (without exceptions) then you'll need the flag the same | 12:38 |
stekern | but SR[DSX] and epcr will differ for the 2 cases | 12:38 |
@juliusb | yes | 12:38 |
@juliusb | well | 12:38 |
@juliusb | i think if you're setting EPCR to the branch you need to set DSX | 12:39 |
@juliusb | to indicate the actual instruction causing the exception was the next one | 12:39 |
stekern | agreed | 12:39 |
@juliusb | whether the branch was taken or not | 12:39 |
@juliusb | and where I differ with this is that I think the exception, if caused by the instruction following a conditional branch which was not taken, should cause the EPCR to be set to that instruction and without DSX set | 12:40 |
@juliusb | but, to, restate, I'm not sure this matters, and if it doesn't then it should be cool if we do it either way | 12:41 |
@juliusb | but then again, maybe it's something which should be standard | 12:41 |
@juliusb | and stated in the arch spec | 12:41 |
@juliusb | and tested for | 12:41 |
stekern | the big Q is "what defines a delay-slot" :) | 12:42 |
stekern | let's just forget about that stupid delay-slot and pretend it never was there | 12:42 |
@juliusb | it's what I've been trying to do ;) | 12:45 |
_franck_ | olofk: I think it is time to apply http://bugzilla.opencores.org/show_bug.cgi?id=104 | 12:46 |
@juliusb | awesome debugging effort on your part here _franck_ | 12:49 |
_franck_ | I love debug :) more than development | 12:50 |
@juliusb | that patch looks good | 12:51 |
_franck_ | I set up an JTAG connector on my altera board so I can use an "external", not vjtag JTAG interface | 12:55 |
_franck_ | I'm going to do an exhaustive testing of all combination for debug i and tap | 12:55 |
@juliusb | oh wow | 12:55 |
@juliusb | hardcore :) | 12:56 |
@juliusb | i've always had to set up the external JTAG connector, though | 12:56 |
@juliusb | it's not so bad :) | 12:56 |
@juliusb | just get some flywires and a few pins somewhere, hey presto | 12:56 |
_franck_ | well we just have deb_if, adv_dbg_if, opencores tap, altera vjtag tap | 12:56 |
_franck_ | I wasn't talking about testing JTAG interfaces | 12:57 |
_franck_ | I'm using an Olimex ARM-USB-blabla right now | 12:57 |
_franck_ | I works good after a patch due to some problem in the openocd ftdi driver | 12:58 |
_franck_ | https://github.com/Franck79/OpenOCD_new/commit/da3725b146843f25d62c044a273cc2b15743bf60 | 12:59 |
@juliusb | hah, someone needs to inform Xilinx what "open" means to a lot of people. From this document: http://www.xilinx.com/support/documentation/white_papers/wp416-Vivado-Design-Suite.pdf | 12:59 |
@juliusb | "Vivado Design Suite is an open design environment that embraces industry standards to leverage the designer’s experience while broadening third-party support. | 13:00 |
@juliusb | I bet it's really open | 13:01 |
@juliusb | _franck_: yeah I know what you mean, you're testing the various combos of stuff inside the chip? | 13:01 |
_franck_ | it's open to cash, credit card and paypal :) | 13:01 |
_franck_ | yes | 13:01 |
@juliusb | haha yep | 13:01 |
@juliusb | _franck_: great. All using OpenOCD I guess? | 13:02 |
_franck_ | yes | 13:02 |
@juliusb | had much of a chance to use the dbg_if? (Mohor one) | 13:02 |
_franck_ | It's working but still have a "bit shift due to TDO register" problem | 13:02 |
_franck_ | I need to take a closer look | 13:02 |
_franck_ | for now, just remove the register in dbg_if | 13:03 |
_franck_ | this old thread: | 13:03 |
_franck_ | http://openrisc.2316802.n4.nabble.com/OpenRISC-openOCD-question-td4457922.html | 13:03 |
@juliusb | I'm not the biggest fan of that nabble.com - too many ads | 13:06 |
@juliusb | you'll find the post here also: | 13:06 |
@juliusb | http://lists.openrisc.net/pipermail/openrisc/2012-March/000734.html | 13:06 |
@juliusb | For the entire archive: http://lists.openrisc.net/pipermail/openrisc/ | 13:06 |
_franck_ | ok | 13:07 |
@juliusb | anyway, did you find a way around it? | 13:07 |
_franck_ | no, still have that patch | 13:08 |
@juliusb | is it something you have to hack the mohor debug unit driver for in OpenOCD? | 13:08 |
_franck_ | for vjtag + mohor debug unit | 13:08 |
@juliusb | right | 13:09 |
@juliusb | that's annoying :-/ | 13:09 |
_franck_ | openocd + opencores tap + dbg_if *should* be ok | 13:09 |
@juliusb | yeah I use that a bit | 13:09 |
_franck_ | that why I want to test every combination | 13:09 |
stekern | _franck_: I agree with the fun of debugging, that's why I constantly go in and break stuff ;) | 13:09 |
@juliusb | btw where is the main openocd repo we use these days? git.openrisc.net? | 13:10 |
_franck_ | openrisc github | 13:10 |
stekern | juliusb: you agreed on moving it to github some week ago | 13:10 |
@juliusb | ok cool, just curious if it happened | 13:15 |
@juliusb | actually, i'd forgotten that particular fact :) but knew it was up in the air a little bit | 13:16 |
@juliusb | is it me or are there a couple of typos in the README.md which is showing up here: https://github.com/openrisc/openOCD | 13:17 |
@juliusb | "JAG VIP driver" | 13:18 |
@juliusb | is that meant to be "JTAG VPI driver"? | 13:18 |
@juliusb | anyway, small issue :) | 13:18 |
@juliusb | very cool, i'll be sure to grab that version next time I run openocd | 13:26 |
@juliusb | _franck_: you mentioned something about attempting to merge with upstream a while back | 13:26 |
@juliusb | any luck with it more recently? | 13:27 |
@juliusb | or are my GDB hacks too incompatible? | 13:27 |
@juliusb | ah, I see the next branch has the latest stuff? | 13:28 |
_franck_ | yes, use the next branch and feel fre to correct README.md typos as you have admin rights on the repo :) | 14:31 |
_franck_ | about merging upstream, I've never really looked at what you're telling is a hack | 14:31 |
_franck_ | if I want to work on gdb, which repo should I use ? | 14:39 |
_franck_ | I guess or1k-src...Anything to know before a try to compile it ? | 14:41 |
@juliusb | This is my hack: https://github.com/openrisc/openOCD/commit/332663c30d77bcfff168288cb6e6f33eec1dcf3a | 16:17 |
@juliusb | those things are used in or1k.c: https://github.com/openrisc/openOCD/blob/next/src/target/or1k.c#L1010 | 16:21 |
@juliusb | so, it's something along the lines of not sending "OK" to the query packets | 16:22 |
@juliusb | I think there's more hackery on this file, though.... | 16:22 |
@juliusb | actually, no the entire readspr/writespr function is based on this hackery, that's right - so for our qRcmd (query remote command or something) | 16:26 |
@juliusb | we just send a string of either "writespr <addr> <data>" or "readspr <addr>" | 16:26 |
@juliusb | and then we respond with the value in ASCII or whatever | 16:26 |
@juliusb | and that's it | 16:27 |
@juliusb | there's no "OK" | 16:27 |
@juliusb | but by default the qRcmd stuff responds with "OK" | 16:27 |
@juliusb | so all I did was something which, in the or1k port, makes sure we only send the data, and not the "OK" | 16:27 |
@juliusb | actually, the or1k GDB shouldn't be using qRcmd to do the SPR reads and wrties | 16:27 |
@juliusb | writes | 16:27 |
@juliusb | there's other mechanisms which are more appropriate | 16:27 |
jeremybennett | qRcmd is the general "communicate with the server" packet. | 16:27 |
jeremybennett | Look at how the monitor commands are implemented may be helpful. | 16:27 |
@juliusb | and it's this workaround in the server which is probably not going to allow us to be merged upstream with OpenOCD | 16:28 |
@juliusb | jeremybennett: yes, from what I gather it's more of a sideband communication thing | 16:28 |
@juliusb | not really intended for debug target comms | 16:28 |
@juliusb | configuring things\ | 16:28 |
@juliusb | anyway, it's another thing for the list of things TODO which we seem to be getting through lately :) | 16:29 |
@juliusb | well, actually, i'm kinda wrong: http://sourceware.org/gdb/onlinedocs/gdb/General-Query-Packets.html#General-Query-Packets | 16:30 |
@juliusb | `qRcmd,command': command (hex encoded) is passed to the local interpreter for execution. | 16:30 |
_franck_ | so qRcmd ends up to .commands handler in the target file in openocd ? right ? | 16:31 |
@juliusb | qXfer is probably what we want | 16:31 |
@juliusb | _franck_: yes | 16:31 |
@juliusb | that "writespr" in the field in that struct corresponds to what the GDB client sends | 16:32 |
_franck_ | ok | 16:32 |
@juliusb | its' pretty cool, stuff like that which OpenOCD just handles for you and provides nice macros and the like | 16:32 |
@juliusb | anyway, for anyone playing with the GDB port in future... | 16:32 |
_franck_ | and normally it uses which handler ? in orther arch ? when reading spr | 16:32 |
* juliusb looks to see if aws is around... | 16:32 | |
@juliusb | _franck_: I don't know how other arches do it to be honest | 16:33 |
_franck_ | ok | 16:33 |
@juliusb | but for or1k I think it makes sense to use teh qXfer stuff a bit more | 16:33 |
@juliusb | `qXfer:object:read:annex:offset,length': Read uninterpreted bytes from the target's special data area identified by the keyword object. Request length bytes starting at offset bytes into the data. | 16:33 |
_franck_ | so jeremybennett do you have the answer to my question about which gdb repo to use ? | 16:34 |
jeremybennett | _franck_: Sorry missed that questions | 16:34 |
jeremybennett | Let me check where we fork for ARC | 16:34 |
_franck_ | it's wasn't especially for you :) | 16:35 |
jeremybennett | git://sourceware.org/git/gdb.git | 16:35 |
_franck_ | I meant gdb for or1k | 16:36 |
jeremybennett | There are mirrors for all the main sourceware modules there, with the exception of CGEN, which you can find at https://github.com/embecosm/cgen | 16:36 |
jeremybennett | I haven't made a GDB one yet. I thought Pete Gavin had done that. | 16:37 |
jeremybennett | The problem is the sourceware upstream (i.e. everything except GCC itself) is in CVS, and uses the CVS module feature to present different slices of one great master repository. | 16:38 |
_franck_ | https://github.com/openrisc/or1k-src/tree/or1k/gdb | 16:38 |
_franck_ | can I compile this ? | 16:38 |
jeremybennett | At present there are only mirrors of particular modules, not the entire source tree. | 16:38 |
jeremybennett | What Pete did, was to take a snaphot of the src tree into GitHub, but I don't know that he regularly updates it from upstream, so it may be out of date. | 16:39 |
jeremybennett | I haven't tried compiling it. | 16:39 |
jeremybennett | We're hoping to put a proper mirror of the entire src tree up in the coming weeks, which will be dynamically updated, and that will the right thing to be forking from. When we do that, I'll try to update the openrisc to be a fork of that. | 16:40 |
_franck_ | I could use this: http://opencores.org/ocsvn/openrisc/openrisc/trunk/gnu-stable | 16:41 |
jeremybennett | So that is the stable SVN version. I haven't worked on it for a year or so though. | 16:42 |
_franck_ | no problem, that's the one I'm using right now | 16:42 |
jeremybennett | OK | 16:43 |
_franck_ | can I go the the gdb directory and just ./configure ? | 16:43 |
_franck_ | or I should use the build script from the root directory | 16:44 |
jeremybennett | None of the GNU tools recommend building in place. Create a build sub-directory (e.g. bd), go there and run ../configure followed by make | 16:45 |
jeremybennett | But using bld-all.sh is safer. I think we've sorted out most of hte common pitfalls. It's based on Mike Frysinger's gentoo scripts. | 16:45 |
jeremybennett | compiling the linux tool chain requires some care, because of hte need to bring in the Linux headers correctly. | 16:46 |
_franck_ | ok I'll do that, I just wanted to save some time while compiling gdb over and over if I'm working on it | 16:46 |
_franck_ | from what I could see in 30 sec, all this hack juliusb did is to handle a special "spr" command in gdb | 16:53 |
_franck_ | add_info ("spr", or32_info_spr_command, | 16:53 |
_franck_ | "Show the value of a special purpose register"); | 16:54 |
_franck_ | I didn't even know we had a spr command in gdb | 16:54 |
LoneTech | I think I nearly have virtual jtag working in openocd (independent of or1k module) | 16:54 |
_franck_ | LoneTech: great | 16:54 |
_franck_ | is it enabled via TCL console ? | 16:56 |
_franck_ | I meant TCL script | 16:57 |
LoneTech | yes | 17:03 |
_franck_ | jeremybennett: you answered to me: http://www.embecosm.com/packages/esp3/embecosm-esp3-or32-gdb-6.8-or1k-manual-html-2.0/or1k_3.html | 17:03 |
_franck_ | LoneTech: when will we have the chance to test it ? :) | 17:04 |
jeremybennett | There was always a "spr" command in OpenRISC GDB. | 17:04 |
_franck_ | I didn't know.... | 17:04 |
jeremybennett | and "info spr" to read the SPR. | 17:04 |
jeremybennett | They are not really what should be used, it would be better IMHO to ahve "set spr" and "show spr" commands. But that's history for you. | 17:05 |
_franck_ | now I understand the whole thing :) the readspr and writespr in openocd are not the problem | 17:06 |
_franck_ | the only problem is the gdb commmand it uses | 17:06 |
jeremybennett | If you use the build script the first time, it will create (from memory) bd-elf-gdb and bd-linux-gdb directories. You can then rebuild just gdb any time, by going to those directories and using "make all-gdb" and "make install-gdb". | 17:06 |
_franck_ | qRcmd and not a another more appropriate | 17:06 |
jeremybennett | That's what I do when working on GDB. | 17:06 |
_franck_ | jeremybennett: ok thanks for the gdb compile info | 17:07 |
jeremybennett | When we moved to use Remote Serial Protocol, I did something to implement the spr and info spr instructions, but I can't remember if it was to use qRcmd. You should be able to see by looking at or32-tdep.c in the SVN copy. | 17:07 |
_franck_ | target_rcmd (cmd, uibuf); | 17:09 |
jeremybennett | Looks like it using qRcmd then. | 17:10 |
_franck_ | so we just need to chnage this to a more appropriate cmd | 17:11 |
_franck_ | qXfer for example like juliusb suggested it | 17:11 |
LoneTech | well, it can now probe the virtual jtag hub (although there's no mapping of instance id to tcl), but I seem to have some mismatch between the mohor module and openocd still | 17:11 |
_franck_ | LoneTech: yes there is a bit shift in between those two | 17:12 |
LoneTech | also, I think there's an issue with IR readback verification since VIR must be selected in an odd manner if it is to be read | 17:12 |
_franck_ | http://lists.openrisc.net/pipermail/openrisc/2012-March/000734.html | 17:12 |
_franck_ | the vjtag as to be set up once at the beginning then it is transparent | 17:13 |
_franck_ | look at the current code using it | 17:13 |
LoneTech | I've seen it. it's just that I'm trying a configuration that I haven't tested before with mohor behind vjtag | 17:14 |
LoneTech | hm, that extra register might be an issue | 17:15 |
_franck_ | it is | 17:16 |
LoneTech | resynthesizing | 17:16 |
LoneTech | looks to me like that register probably belongs in the gpio jtag tap module instead | 17:17 |
LoneTech | since we can't really remove one from the virtual jtag module | 17:17 |
jeremybennett | _franck_: I haven't followed the full discussion as to why qRcmd is not appropriate. But GDB does have the concept of "auxilliary register", and we should use the commands to handle those for SPRs. | 17:17 |
jeremybennett | Actually we should be using the XML functionality to allow the user to describe the target features. | 17:18 |
_franck_ | qRcmd should responf with "OK" but we are responding with a value | 17:21 |
LoneTech | removing that register didn't really help. I think there's a slightly bigger mismatch involved. | 17:22 |
LoneTech | Error: received CRC (0x002bfd47) not same as calculated CRC (0xfff06cbb) | 17:22 |
LoneTech | Error: received CRC (0x00000000) not same as calculated CRC (0xbc16f9b6) | 17:22 |
_franck_ | does it work with the openOCD version in the openrisc github repo ? | 17:23 |
_franck_ | (it does work when removing this reg in dbg_if) | 17:24 |
LoneTech | I tested gpio jtag without removing that register before, which did work | 17:25 |
_franck_ | because they are working well together | 17:25 |
_franck_ | the is a gpio tap version along with adv_debug_if: | 17:26 |
_franck_ | http://opencores.org/websvn,filedetails?repname=adv_debug_sys&path=%2Fadv_debug_sys%2Ftrunk%2FHardware%2Fjtag%2Ftap%2Frtl%2Fverilog%2Ftap_top.v | 17:26 |
_franck_ | there is a tdo register mismach, Marek Czerski is preparing a patch to fix this | 17:27 |
LoneTech | well, the 4-bit status carries an invalid value per the mohor debug module documentation. I guess that's something. | 17:35 |
LoneTech | afaict the virtual jtag layer itself is working (albeit misplaced and a crude hack) | 17:37 |
LoneTech | but the only combination of openocd I got to work is mohor with gpio jtag so far | 17:37 |
_franck_ | :( too bad | 17:38 |
LoneTech | some part of me feels a 32-bit crc for a 4-bit packet is a bit overkill. | 17:38 |
olofk | Great to hear some gdb talk. | 19:56 |
olofk | And regarding the mohor debug unit. There is some bit shift patch applied to the orpsocv2 copy that isn't in the upstream version | 19:57 |
olofk | But as everyone soon will be using orpsocv3, those differences won't be a problem :) | 19:58 |
_franck_ | jeremybennett: I'm going to use this xml thing in gdb. I now understand it :) | 21:11 |
Generated by irclog2html.py 2.15.2 by Marius Gedminas - find it at mg.pov.lt!